select..for update

update, insert ,delete, select ... for update会LOCK相应的ROW 。
只有一个TRANSACTION可以LOCK相应的行,也就是说如果一个ROW已经LOCKED了,那就不能被其他TRANSACTION所LOCK了。
LOCK由statement产生但却由TRANSACTION结尾(commit,rollback),也就是说一个SQL完成后LOCK还会存在,只有在COMMIT/ROLLBACK后才会RELEASE。xsb注:同样的道理, 如果一个游标使用了for update打开后,虽然关闭了游标,但这个lock也仍是存在的,直到transaction结束!
SELECT.... FOR UPDATE [OF cols] [NOWAIT];

SELECT cols FROM tables [WHERE...] FOR UPDATE [OF cols] [NOWAIT];
transaction A运行
select a.c1,a.c2 from t1 a,t2 b
2 where b.c3=1 and a.c1=b.c1
3* for update of a.c2
此时transaction B可以对b表t2的相应行进行DML操作,但不能对a表t1相应行进行DML操作.
再看:
transaction A运行
select a.c1,a.c2 from t1 a,t2 b
2 where b.c3=1 and a.c1=b.c1
3* for update of b.c2
此时transaction B可以对a表t1的相应行进行DML操作,但不能对b表t2相应的行进行DML操作.
也就是说LOCK的仍然是行,只是如果不加OF的话会对所有涉及的表LOCK,加了OF后只会LOCK OF 字句所在的TABLE.
NOWAIT(如果一定要用FOR UPDATE,可以加上NOWAIT)
当有LOCK冲突时会提示错误并结束STATEMENT,返回错误是"ORA-00054: resource busy and acquire with NOWAIT specified",否则就会在那里等待。
另外如下用法也值得推荐,应该酌情考虑使用。
FOR UPDATE WAIT 5
5秒后会提示ORA-30006: resource busy; acquire with WAIT timeout expired
FOR UPDATE NOWAIT SKIP LOCKED;
会提示no rows selected
TABLE LOCKS
LOCK TABLE table(s) IN EXCLUSIVE MODE [NOWAIT];
同样也是在transaction结束时才会释放lock。
DEADLOCK
transaction a lock rowA , then transaction b lock rowB
then transaction a tries to lock rowB, and transaction b tries to lock rowA
也就是说两个transaction都相互试图去lock对方已经lock的ROW,都在等待对方释放自己的lock,这样就使死锁。deadlock也会有600提示。

你可能感兴趣的:(select..for update)