Oracle数据库中锁定的标准别保证了最大可能的q发U别也就是说,如果某个会话正在更新一条记?那么只有q条记录会被锁定.此外,锁定q条记录是ؓ了防止其他会话对其进行更?其他会话可以随时执行d操作.只有在用commit或rollback命ol束事务之后,锁定才会被解?q种锁定是一?#8221;排他?#8221;:在指定记录上h排他锁的W一个会话会得到q个锁定,其他h对该记录q行写访问的会话则必ȝ?虽然q条记录已通过锁定会话q行了更?但是对其q行读访问你是被允许?而且l常会出现这U情?,q且q些L作会涉及撤销数据的?从而确保都会回q不会看CQ何未被提交的变化对于一条记录或一个完整表上的一个排他锁来说,每次只能有一个会话可以获得这个排他锁,不过许多会话可以同时获得相同对象上的”׃n?#8221;.在一条记录上讄׃n锁毫无意?其原因在于锁定一条记录的唯一目的是不允许其他会话更改它.׃n锁被|于整个表上,同时许多会话可以获得同一个表上的׃n?在一个表上放|共享锁的目的是Z防止另一个会话获得这个表上的排他?在已存在׃n锁的情况下无法再获得排他?.在表上防止排他锁是需要执行DDL语句.如果其他M会话已经在一个表上放|了׃n?那么我们无法执行修Ҏ个对象的语句(例如删除q个表的某一?.
Z在记录上执行DML语句,当前会话必须获取待更新记录上的排他锁以及包含q些记录的表上的׃n?如果另一个会话已l获取了待更新记录上的排他锁,那么当前会话被挂v,直至使用COMMIT或ROLLBACK命o解除q些锁定,如果另一个会话已l获取了待修改记录的表上的共享锁以及其他记录上的排他?那么׃存在M问题.一个表上的排他锁会锁定q个?但是,如果不需要执行DDL语句,那么我们可以不锁定整个表的默认锁定机制.
提示:只有在特别请求ƈ且编Eh员具有充分理q情况?才可以要求在整个表上攄排他?
DML锁与DDL?/strong>
所有DML语句都至需要两U锁?受媄响记录上的排他锁,以及包含受媄响记录的表上的共享锁.排他锁能够防止其他会话干预指定的记录,而共享锁则能够阻止其他会话用DDL语句修改表的定义.q两U锁定会被自动请?如果某条DML语句在指定记录上无法获取所需的排他锁,那么q条语句会被挂v直至获得所需的排他锁.
执行DDL命o需要用所涉及对象上的排他?只有在针Ҏ定表的所有DML事务l束,q且记录上的排他锁以及表上的׃n锁都被解除之?我们才可以获得执行DDL命o所需的排他锁,MDDL语句所需的排他锁都是被自动请求的.但是,如果无法获取所需的排他锁(通常是因为其他会话已l获得用于DML语句的共享锁),那么DDL语句׃׃错误立即l止.
例子:
1. 使用SQL*PLUS,作ؓ用户SYSTEMq接数据?
2. 创徏一个表,q且在这个表中插入一条记?
>create table t1(c1 number);
>insert into t1 values(1);
>commit;
3.再次使用SQL*PLUSq作为用户SYSTEMq行q接,从而打开另一个会?
4.在第一个会话中执行一个DML命o,q个命o会在插入的记录上攄一个排他锁,同时q会在创建的表上攄一个共享锁.
>update table t1 set c1=2 where c1=1;
5.如下所C?在第二个会话中执行第一条针Ҏ的DDL语句.
>alter table t1 add(c2 date);
error at line 1:
ora-00054:resource busy and acquire with nowait specified
因ؓDDL语句需要表上的排他?而这与DML语句已在表上攄了共享锁相冲H?所以试囑֜表中插入一个列的这条DDL语句会失?需要注意的?在类似情况下,DML语句会等待ƈ不断q行试,直至获得其所需的锁(换句话说是挂v);而DDL语句则会׃错误立即l止.
6.在第一个会话中,提交当前事务
>commit;
7.在第二个会话?重新执行步骤5.此时,因ؓ不纯在与DDL排他锁相冲突的DML׃n?因此DDL语句成功的执行.
8.在第一个会话中 ,锁定整个?
>lock table t1 in exclusive mode;
9.在第二个会话?插入一条记?此时,q个会话被挂v.
>insert into t1 values (1,sysdate);
10.在第一个会话中,通过执行COMMIT命o解除整个表上的锁?需要注意的?ROLLBACK命o也可以实现相同的目的.
>commit;
11.W二个会话会释放q且现在会完成插入操?随后,执行COMMIT命o,l止当前事务斌且解除该记录上的排他锁.
关于如何解决死锁的问?
Q?查哪个过E被?br />
查V$DB_OBJECT_CACHE视图:
SELECT * FROM V$DB_OBJECT_CACHE WHERE OWNER=''q程的所属用?' AND LOCKS!=''0'';
2. 查是哪一个SID,通过SID可知道是哪个SESSION.
查V$ACCESS视图:
SELECT * FROM V$ACCESS WHERE OWNER=''q程的所属用?' AND NAME=''刚才查到的过E名
版权归原作者和各发布网站所有,此文章仅供学习参考之?/em>