FOR UPDATE OF和FOR UPDATE之间的区别

时间:2013-04-18 11:22:22

标签: oracle locking sql-update

当我使用FOR UPDATE OF SAL或只是写FOR UPDATE时,有什么不同。

根据O'Reilly

  

FOR UPDATE子句的OF列表不限制您更改   只列出那些列。锁仍然放在所有行上; OF   list只是为您提供了一种更清楚地记录您的意图的方法   更改。如果您只是在查询中声明FOR UPDATE而不包括   在OF关键字之后的一个或多个列,然后数据库将   锁定FROM子句中列出的所有表中所有标识的行。

这意味着,当我使用FOR UPDATE OF SAL指定列名时,其他用户只能使用SAL列进行更改。但实际情况并非如此。我还在锁定其他会话。任何人都可以解释这种差异。

更新

 ----- SESSION 1

declare
 emp_info emp.ename%type;
 cursor emp_cur is select ename from emp join dept using(deptno) where deptno=&no for update of sal;
 begin
 open emp_cur;
 loop
 fetch emp_cur into emp_info;
 exit when emp_cur%notfound;
 dbms_output.put_line(emp_info);
 end loop;
 close emp_cur;
 end;

  ----- SESSION 2

  update emp set comm=5 where deptno=10;
  ---- hanged/waiting in session 2

2 个答案:

答案 0 :(得分:16)

来自Oracle documentation

  

使用OF ...列子句仅锁定a的选择行   连接中的特定表或视图。仅OF子句中的列   指示哪些表或视图行被锁定。具体栏目   您指定的并不重要。但是,您必须指定一个   实际列名,而不是列别名。如果你省略这个条款,那么   数据库锁定查询中所有表中的选定行。

如果您的查询引用了单个表,则FOR UPDATEFOR UPDATE OF ...之间没有区别,但后者可能仍然可用作自我文档以指示您要更新的列。它不限制你可以更新的内容。如果你有:

CURSOR cur IS SELECT * FROM emp FOR UPDATE OF sal;

然后你仍然可以这样做:

UPDATE emp SET comm = comm * 1.1 WHERE CURRENT OF cur;

但是如果有多个表,那么FOR UPDATE OF ...将仅锁定包含您在OF子句中指定的列的表中的行。

与我认为你在问题中所说的相反。指定FOR UPDATE OF sal不仅会锁定sal列;您永远不能锁定单个列,最小锁定在行级别。 (Read more about locks)。它会锁定包含SAL列的表中的所有行,这些行由查询选择。


在您的问题更新中,您的光标查询正在加入empdept,但OF子句只有sal,{{1表。打开游标时,emp表中的行将被锁定,并且在您empcommit该会话之前,这些锁将不会被释放。在光标循环中,您可以执行以下操作:

rollback

...更新UPDATE emp SET ... WHERE CURRENT OF emp_cur; 表中与此循环迭代相关的行。你不能做:

emp

...因为UPDATE dept SET ... WHERE CURRENT OF emp_cur; 表中的行未锁定,因为dept中没有列。这也意味着在第二个会话中OF行可以自由更新,因为它们没有被第一个会话锁定。

答案 1 :(得分:0)

有关更新的另外一条评论。如果您从多个表中进行选择,并且没有where子句来引用更新的每个表,那么它将锁定所有表,直到更新完成。

相关问题