Rav*_*avi 8 oracle locking sql-update
当我使用FOR UPDATE OF SAL或简单地写时,有什么不同FOR UPDATE.
根据奥莱利的说法
FOR UPDATE子句的OF列表不限制您仅更改列出的列.锁仍然放在所有行上; OF列表只是为您提供了一种更清楚地记录您想要更改的内容的方法.如果您只是在查询中声明FOR UPDATE并且在OF关键字之后不包含一个或多个列,那么数据库将锁定FROM子句中列出的所有表中的所有标识的行.
这意味着,当我指定列名时FOR UPDATE OF SAL,其他用户只能使用SAL列进行更改.但实际情况并非如此.我还在锁定其他会话.任何人都可以解释这种差异
UPDATE
----- 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
Run Code Online (Sandbox Code Playgroud)
Ale*_*ole 17
从Oracle文档:
使用
OF ...column子句仅锁定连接中特定表或视图的选择行.OF子句中的列仅指示锁定哪些表或视图行.您指定的特定列不重要.但是,您必须指定实际的列名称,而不是列别名.如果省略此子句,则数据库将锁定查询中所有表中的选定行.
如果您的查询引用单个表,则FOR UPDATE和之间没有区别FOR UPDATE OF ...,但后者可能仍然可用作自我文档以指示您要更新的列.它不限制你可以更新的内容.如果你有:
CURSOR cur IS SELECT * FROM emp FOR UPDATE OF sal;
Run Code Online (Sandbox Code Playgroud)
然后你仍然可以做:
UPDATE emp SET comm = comm * 1.1 WHERE CURRENT OF cur;
Run Code Online (Sandbox Code Playgroud)
但是,如果有多个表,则FOR UPDATE OF ...只会锁定包含您在OF子句中指定的列的表中的行.
与我认为你在问题中所说的相反.指定FOR UPDATE OF sal不仅会锁定sal列; 您永远不能锁定单个列,最小锁定在行级别.(阅读更多关于锁的信息).它锁定包含SAL列的表中的所有行,这些行由查询选择.
在更新你的问题,你的光标查询加入emp和dept,但OF条款只sal,在一列emp的表.emp打开游标时,表中的行将被锁定,并且在您commit或rollback该会话之前不会释放这些锁.在游标循环中,您可以:
UPDATE emp SET ... WHERE CURRENT OF emp_cur;
Run Code Online (Sandbox Code Playgroud)
...更新emp表中与循环迭代相关的行.你不能做的:
UPDATE dept SET ... WHERE CURRENT OF emp_cur;
Run Code Online (Sandbox Code Playgroud)
...因为dept表中的行没有被锁定,因为没有列OF.这也意味着在第二个会话中,dept行可以自由更新,因为它们不会被第一个会话锁定.
| 归档时间: |
|
| 查看次数: |
29315 次 |
| 最近记录: |