只有一个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提示。
查询不会锁表。 oracle的锁机制很棒,你平常根本不用考虑锁这个问题,可以当它是透明的。2楼说的是oracle的:select * from table for update;
Read committed: Not possible(Dirty Read) Possible(NonRepeatable Read) Possible(Phantom Read)
Repeatable read: Not possible(Dirty Read) Not possible(NonRepeatable Read) Possible(Phantom Read)
Serializable: Not possible(Dirty Read) Not possible(NonRepeatable Read) Not possible(Phantom Read)可见,正常情况下select只会发生NonRepeatable Read和Phantom Read现象. SQL四种隔离级别都有,oracle是支持read committed和serializable,但提供read-only
select * from dual for update; 锁表 select * from dual; 不锁表
只有一个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提示。
oracle的锁机制很棒,你平常根本不用考虑锁这个问题,可以当它是透明的。2楼说的是oracle的:select * from table for update;
我只是把Oracle的部分数据导到MySQL里,程序自己写
常规操作什么时候加锁:
UPDATE 为WHERE条件部分的行加锁
DELETE 为WHERE条件部分加锁
INSERT INSERT部分加锁(粒度很小),几乎不造成阻塞
SELECT FOR UPDATE 对WHERE条件的行加锁。上述行级锁会相互阻塞。对于同对象的加锁,ORACLE会进行序列化过程(因为加锁也是一行一行加的,如果你要锁1000行,在锁住999行的时候,另外一个事务将那行锁住了,就死掉了),对于多个对象交叉锁ORACLE已经可以监控到。普通的SELECT语句不会阻塞,也不会受到阻塞(不过这个阻塞只是锁方面的阻塞,不是指由于海量数据返回中造成的网络阻塞),可以通过两个会话进行测试,一个语句使用SELECT FOR UPDATE并不关闭,另一个开启普通SELECT可以照常查询,不过不能保证运行中不读出脏数据,对于脏数据读要求不要的系统没必要那么精确,因为很影响性能当上述锁长期锁住的时候,通过视图v$locked_object可以查看到,并可以定位是那个SESSION_ID和对象ID,通过SESSION_ID到视图v$session可以找到对应的SID和SERIAL#字段,可以强制删除掉这个SESSION,而通过对象ID可以到USER_OBJECTS或DBA_OBJECTS视图中查看到那个对象被锁住了,几个视图可以关联起来查询。
Read uncommitted:
Possible(Dirty Read)
Possible(NonRepeatable Read)
Possible(Phantom Read)
Read committed:
Not possible(Dirty Read)
Possible(NonRepeatable Read)
Possible(Phantom Read)
Repeatable read:
Not possible(Dirty Read)
Not possible(NonRepeatable Read)
Possible(Phantom Read)
Serializable:
Not possible(Dirty Read)
Not possible(NonRepeatable Read)
Not possible(Phantom Read)可见,正常情况下select只会发生NonRepeatable Read和Phantom Read现象.
SQL四种隔离级别都有,oracle是支持read committed和serializable,但提供read-only
select * from dual; 不锁表
select ...for update会锁表
不过多年前使用toad好像会有锁表的情况 记不得了
如果有 就是bug
可能我对于脏数据的理解有点问题吧,不过在曾经的几个试验中以及参考相关资料得到相应信息,如以下两个实验:1、模拟银行转账+查询账户,这里当然模拟极限情况,转账需要做两个动作就是分别UPDATE,并最后COMMIT,那么为了模拟,可以再两个UPDATE之间做一个dbms_lock.sleep(10)休息十秒钟,在这里开启另一个SESSION你可以用SELECT读一下表,肯定是修改前的数据,这个至少我认为是脏数据,因为即使数据在修改中,但是毕竟修改了。2、做一个过程或者统计,不过做过程更容易模拟,这个过程用断点去走,可以模拟一个SQL,也可以模拟一个游标,在过程的断点走掉中间的时候还未结束,开启另一个会话对游标查询的表进行增、删、改、查操作,并使用COMMIT,你看下你游标遍历出来的数据是什么,肯定是另一个会话对表修改前的数据,因为任何执行语句都会带上时间戳并对应其SCN号码,数据若发现SCN号码和带入的SCN号码不一致,则到回滚段中查找数据,若回滚段中没有了,执行语句会报错。。另外还有强制通过版本号或者时间戳查询历史修改数据的(可以存放多少是和回滚段大小有关系,存放时间还除和大小有关系还和系统经常发生的业务频繁操作量也有关系),也就是强制到回滚段中查询的。
BZW,关于ORACLle查询会不会锁表,我个人认为要从控制并发的锁机制和事务隔离级别上去考虑,他们是相互关联的.不管MS SQL SERVER还是ORACLE,只要是缺省的隔离级别,且不人工加上锁,查询是不会锁其他表,其他表的操作也不会阻塞查询操作的(最多会产生不可重复读和幻读),反之,就可能不是查询操作阻塞其他操作,就是其他操作阻塞本查询.
理解。TKS脏数据这个概念的确是我自己弄错了,呵呵