Chinaunix首页 | 论坛 | 博客
  • 博客访问: 210890
  • 博文数量: 51
  • 博客积分: 2505
  • 博客等级: 少校
  • 技术积分: 595
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-20 16:59
文章分类

全部博文(51)

文章存档

2010年(5)

2009年(39)

2008年(7)

我的朋友

分类:

2009-06-24 13:16:34

有如下代码:

declare

    --
query emp.name

    cursor cur_emp

        is

    select empno
, ename, job

      from emp

     where empno
= 7369

      
for update of ename;

begin

   
for return_cur in cur_emp

    loop   

       update emp

          set ename
= 'LHG'

       
where current of cur_emp;

   
end loop;

end;

其中的for update of ename意思是给表中的行加锁,经过测试,后面的ename可以写成该表中的任何字段,因为oracle中锁的最低级别是行锁,不存在给字段加锁。

下面是行锁的作用:

1.行锁开始于一个CURSOR的OPEN,结束于一个提交COMMIT或ROLLBACK,而并不是结束于一个CURSOR的结束(CLOSE)。

2.当在一个CURSOR中对某个表的行加锁,那么如果在这个SESSION中用另一个CURSOR操作该行记录时候会等待第一个cursor的完成提交,直到第一个cursor提交完成之后,第二个cursor中对改行的操作才会开始执行。

3.当第一个cursor中的由于操作错误而不能提交时候,第二个cursor将会一直等待下去,这样就形成了死锁。预防这种情况发生的方法是在for update of ename 之后指定NOWAIT选项,这样的话,当第二个cursor不会一直等待下去,而是出现ORA-00054 [resource busy and acquire with NOWAIT specified]
讯息。

4.既然for update of后面的字段是随便那个字段都可以,那么可不可以不写呢?如果你没必要指定NOWAIT选项,那么后面的字段就可以不写;如果你必须指定NOWAIT选项,则必须指定至少一个字段。

5.还有一种方法是用ROWID替代WHERE CURRENT OF YOUR_CURSOR_NAME语句。

如下代码:

declare

     --
query emp.name

     cursor cur_emp

         is

     select a
.deptno,

           
a.dname,

           
a.rowid,

           
b.rowid rowid_1

       from dept a
, emp b

      where empno
= 7369

       
and a.deptno = b.deptno

       
for update nowait;



     --
local variables

     v_deptno dept
.deptno%type;

    
v_dname dept.dname%type;

    
v_rowid rowid;

    
v_rowid_1 rowid;



begin

     open cur_emp
;

    
loop

     fetch cur_emp into v_deptno
, v_dname, v_rowid, v_rowid_1;

     exit
when cur_emp%notfound;



       
update dept

           set dname
= 'abc'

        
where rowid = v_rowid;



       
update emp

           set ename
= 'frank'

        
where rowid = v_rowid_1;



    
end loop;

    
close cur_emp;

    
commit;

exception

     when others then

        rollback
;

       
raise;

end;

由此,推荐的for update的习惯是:

  • NOWAIT定然跟FOR UPDATE之后。
  • 直接用ROWID替代WHERE CURRENT OF YOUR_CURSOR_NAME语句,
    尤其在相对繁习的程序里头。
  • COMMIT必需存在程序结尾。以防死锁成形。
  • EXCEPTION里的ROLLBACK是最基本的需要。
  • 阅读(6597) | 评论(0) | 转发(0) |
    给主人留下些什么吧!~~