`
zhangpeng012310
  • 浏览: 61104 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

SELECT FOR UPDATE 相关的知识 转载

阅读更多
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提示。



statement: 一个SQL语句。


session: 一个由ORACLE用户产生的连接,一个用户可以产生多个SESSION ,但相互之间是独立的。

transaction:所有的改变都可以划分到transaction里,一个 transaction包含一个或多个SQL。当一个SESSION建立的时候就是一个TRANSACTION开始的时刻,此后transaction的 开始和结束由DCL控制,也就是每个COMMIT/ROLLBACK都标示着一个transaction的结束。

consistency:是对于statement级别而不是transaction级别来说的。sql statement 得到的数据都是以sql statement开始的IMAGE。

LOCK的基本情况:

update, insert ,delete, select ... for update会LOCK相应的ROW 。

只有一个TRANSACTION可以LOCK相应的行,也就是说如果一个ROW已经LOCKED了,那就不能被其他TRANSACTION所LOCK了。

LOCK由statement产生但却由TRANSACTION结尾(commit,rollback),也就是说一个SQL完成后LOCK还会存在,只有在COMMIT/ROLLBACK后才会RELEASE。

SELECT.... FOR UPDATE [OF cols] [NOWAIT];OF colsSELECT cols FROM tables [WHERE...] FOR UPDATE [OF cols] [NOWAIT];

前面的FOR UPDATE省略,下面我们来讲一下OF。

transaction A运行select a.object_name,a.object_id from wwm2 a,wwm3 b2 where b.status='VALID' and a.object_id=b.object_id3* for update of a.status

则transaction B可以对b表wwm3的相应行进行DML操作,但不能对a表wwm2相应行进行DML操作.

反一下看看。

transaction A运行select a.object_name,a.object_id from wwm2 a,wwm3 b2 where b.status='VALID' and a.object_id=b.object_id3* for update of b.status

则transaction B可以对a表wwm2的相应行进行DML操作,但不能对b表wwm3相应行进行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 expiredFOR UPDATE NOWAIT SKIP LOCKED;

出现提示:

no rows selectedTABLE LOCKSLOCK TABLE table(s) IN EXCLUSIVE MODE [NOWAIT];

同样也是在transaction结束时才会释放lock。

DEADLOCK:

transaction a lock rowA , then transaction b lock rowBthen transaction a tries to lock rowB, and transaction b tries to lock rowA

也就是说两个transaction都相互试图去lock对方已经lock的ROW,都在等待对方释放自己的lock,这样就使死锁。另外,deadlock也会有600提示。

使用说明

Select…For Update语句的语法与select语句相同,只是在select语句的后面加FOR UPDATE [NOWAIT]子句。

该语句用来锁定特定的行(如果有where子句,就是满足where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被commit语句或rollback语句结束为止。

如 图20.51所示,左上角的会话用Select…For Update语句锁定了Department表中DeptNo='01'的行,右上角的会话说明其他会话不可以继续更改该行上的数据。从OEM中的锁的信 息可以看出,Select…For Update语句所加的锁与update语句所加的锁相同:一个行级别的EXCLUSIVE锁(说明多个事务不能同时操作同一行)、一个表级别的ROW EXCLUSIVE锁。



图20.51   Select…For Update语句锁定了符合where条件的行
如图20.52所示,左上角的会话用Update语句锁定了Department表中DeptNo='01'的行,右上角的会话说明其他会话不可以用Select…For Update语句继续锁定该行。



图20.52   Select…For Update语句被其他会话阻塞了
如 图20.53所示,左上角的会话用Update语句锁定了Department表中DeptNo='01'的行,右上角的会话说明其他会话不可以用 Select…For Update NOWAIT语句继续锁定该行,且会立即返回一个错误提示“ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源”,而不需要等待加锁成功。



图20.53    如果加锁不成功,则Select…For Update NOWAIT语句就会立即返回错误提示
可 以看出,如果仅仅用update语句来更改数据时,可能会因为加不上锁而没有响应地、莫名其妙地等待,但如果在此之前,先用Select…For Update NOWAIT语句将要更改的数据试探性地加锁,就可以通过立即返回的错误提示而明白其中的道理,或许这就是For Update和NOWAIT的意义之所在。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics