当我使用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
答案 0 :(得分:16)
使用
OF ...
列子句仅锁定a的选择行 连接中的特定表或视图。仅OF
子句中的列 指示哪些表或视图行被锁定。具体栏目 您指定的并不重要。但是,您必须指定一个 实际列名,而不是列别名。如果你省略这个条款,那么 数据库锁定查询中所有表中的选定行。
如果您的查询引用了单个表,则FOR UPDATE
和FOR 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
列的表中的所有行,这些行由查询选择。
在您的问题更新中,您的光标查询正在加入emp
和dept
,但OF
子句只有sal
,{{1表。打开游标时,emp
表中的行将被锁定,并且在您emp
或commit
该会话之前,这些锁将不会被释放。在光标循环中,您可以执行以下操作:
rollback
...更新UPDATE emp SET ... WHERE CURRENT OF emp_cur;
表中与此循环迭代相关的行。你不能做:
emp
...因为UPDATE dept SET ... WHERE CURRENT OF emp_cur;
表中的行未锁定,因为dept
中没有列。这也意味着在第二个会话中OF
行可以自由更新,因为它们没有被第一个会话锁定。
答案 1 :(得分:0)
有关更新的另外一条评论。如果您从多个表中进行选择,并且没有where子句来引用更新的每个表,那么它将锁定所有表,直到更新完成。