文章转自:http://www.blogjava.net/imdosop/archive/2008/11/07/239266.html
Oracle锁机制锁问题的详细分析
在任何多用户数据库应用中,最终必然会出现两个用户希望同时处理相同记录的情况.这种情况在逻辑上是不可能的,并且数据库必须确保其在物理上也是不可能的.事务隔离性原则要求数据库保证:在 ,这个会话无法影响另一个会话,并且后者也无法看到前者.为了实现这个要求,数据库创行话并发的数据访问,甚至在多个会话请求访问相同的记录时,数据库也必须确保这些会话排队依次进行.
借助于记录和表锁定机制,我们可以实现并发的串行化.oracle数据库中的锁定是完全自动的.一般而言,只有在试图结合软件与自动锁定机制是或者编程人员编写的代码太糟糕时才会引发某些问题.
共享锁与排他锁
Oracle数据库中锁定的标准级别保证了最大可能的并发级别也就是说,如果某个会话正在更新一条记录,那么只有这条记录会被锁定.此外,锁定这条记录是为了防止其他会话对其进行更新,其他会话可以随时执行读取操作.只有在使用commit或rollback命令结束事务之后,锁定才会被解除.这种锁定是一个”排他锁”:在指定记录上请求排他锁的第一个会话会得到这个锁定,其他请求对该记录进行写访问的会话则必须等待.虽然这条记录已通过锁定会话进行了更新,但是对其进行读访问你是被允许的(而且经常会出现这种情况),并且这些读操作会涉及撤销数据的使用,从而确保都会回并不会看到任何未被提交的变化对于一条记录或一个完整表上的一个排他锁来说,每次只能有一个会话可以获得这个排他锁,不过许多会话可以同时获得相同对象上的”共享锁”.在一条记录上设置共享锁毫无意义,其原因在于锁定一条记录的唯一目的就是不允许其他会话更改它.共享锁被置于整个表上,同时许多会话可以获得同一个表上的共享锁.在一个表上放置共享锁的目的是为了防止另一个会话获得这个表上的排他锁(在已存在共享锁的情况下无法再获得排他锁).在表上防止排他锁是需要执行DDL语句.如果其他任何会话已经在一个表上放置了共享锁,那么我们就无法执行修改某个对象的语句(例如删除这个表的某一列).
为了在记录上执行DML语句,当前会话必须获取待更新记录上的排他锁以及包含这些记录的表上的共享锁.如果另一个会话已经获取了待更新记录上的排他锁,那么当前会话将被挂起,直至使用COMMIT或ROLLBACK命令解除这些锁定,如果另一个会话已经获取了待修改记录的表上的共享锁以及其他记录上的排他锁,那么就不存在任何问题.一个表上的排他锁会锁定这个表,但是,如果不需要执行DDL语句,那么我们就可以不锁定整个表的默认锁定机制.
提示:只有在特别请求并且编程人员具有充分理由的情况下,才可以要求在整个表上放置排他锁.
DML锁与DDL锁
所有DML语句都至少需要两种锁定:受影响记录上的排他锁,以及包含受影响记录的表上的共享锁.排他锁能够防止其他会话干预指定的记录,而共享锁则能够阻止其他会话使用DDL语句修改表的定义.这两种锁定会被自动请求.如果某条DML语句在指定记录上无法获取所需的排他锁,那么这条语句会被挂起直至获得所需的排他锁.
执行DDL命令需要使用所涉及对象上的排他锁.只有在针对指定表的所有DML事务结束,并且记录上的排他锁以及表上的共享锁都被解除之后,我们才可以获得执行DDL命令所需的排他锁,任何DDL语句所需的排他锁都是被自动请求的.但是,如果无法获取所需的排他锁(通常是因为其他会话已经获得用于DML语句的共享锁),那么DDL语句就会由于错误立即终止.
例子:
1. 使用SQL*PLUS,作为用户SYSTEM连接数据库.
2. 创建一个表,并且在这个表中插入一条记录.
>create table t1(c1 number);
>insert into t1 values(1);
>commit;
3.再次使用SQL*PLUS并作为用户SYSTEM进行连接,从而打开另一个会话.
4.在第一个会话中执行一个DML命令,这个命令会在插入的记录上放置一个排他锁,同时还会在创建的表上放置一个共享锁.
>update table t1 set c1=2 where c1=1;
5.如下所示,在第二个会话中执行第一条针对新建表的DDL语句.
>alter table t1 add(c2 date);
error at line 1:
ora-00054:resource busy and acquire with nowait specified
因为DDL语句需要表上的排他锁,而这与DML语句已在表上放置了共享锁相冲突,所以试图在表中插入一个列的这条DDL语句会失败.需要注意的是:在类似情况下,DML语句会等待并不断进行尝试,直至获得其所需的锁(换句话说就是挂起);而DDL语句则会由于错误立即终止.
6.在第一个会话中,提交当前事务
>commit;
7.在第二个会话中,重新执行步骤5.此时,因为不纯在与DDL排他锁相冲突的DML共享锁,因此DDL语句将成功的执行.
8.在第一个会话中 ,锁定整个表.
>lock table t1 in exclusive mode;
9.在第二个会话中,插入一条记录.此时,这个会话将被挂起.
>insert into t1 values (1,sysdate);
10.在第一个会话中,通过执行COMMIT命令解除整个表上的锁定.需要注意的是,ROLLBACK命令也可以实现相同的目的.
>commit;
11.第二个会话会释放并且现在会完成插入操作.随后,执行COMMIT命令,终止当前事务斌且解除该记录上的排他锁.
关于如何解决死锁的问题.
1.查哪个过程被锁
查V$DB_OBJECT_CACHE视图:
SELECT * FROM V$DB_OBJECT_CACHE WHERE OWNER=''过程的所属用户'' AND LOCKS!=''0'';
2. 查是哪一个SID,通过SID可知道是哪个SESSION.
查V$ACCESS视图:
SELECT * FROM V$ACCESS WHERE OWNER=''过程的所属用户'' AND NAME=''刚才查到的过程名
Oracle锁机制锁问题的详细分析
在任何多用户数据库应用中,最终必然会出现两个用户希望同时处理相同记录的情况.这种情况在逻辑上是不可能的,并且数据库必须确保其在物理上也是不可能的.事务隔离性原则要求数据库保证:在 ,这个会话无法影响另一个会话,并且后者也无法看到前者.为了实现这个要求,数据库创行话并发的数据访问,甚至在多个会话请求访问相同的记录时,数据库也必须确保这些会话排队依次进行.
借助于记录和表锁定机制,我们可以实现并发的串行化.oracle数据库中的锁定是完全自动的.一般而言,只有在试图结合软件与自动锁定机制是或者编程人员编写的代码太糟糕时才会引发某些问题.
共享锁与排他锁
Oracle数据库中锁定的标准级别保证了最大可能的并发级别也就是说,如果某个会话正在更新一条记录,那么只有这条记录会被锁定.此外,锁定这条记录是为了防止其他会话对其进行更新,其他会话可以随时执行读取操作.只有在使用commit或rollback命令结束事务之后,锁定才会被解除.这种锁定是一个”排他锁”:在指定记录上请求排他锁的第一个会话会得到这个锁定,其他请求对该记录进行写访问的会话则必须等待.虽然这条记录已通过锁定会话进行了更新,但是对其进行读访问你是被允许的(而且经常会出现这种情况),并且这些读操作会涉及撤销数据的使用,从而确保都会回并不会看到任何未被提交的变化对于一条记录或一个完整表上的一个排他锁来说,每次只能有一个会话可以获得这个排他锁,不过许多会话可以同时获得相同对象上的”共享锁”.在一条记录上设置共享锁毫无意义,其原因在于锁定一条记录的唯一目的就是不允许其他会话更改它.共享锁被置于整个表上,同时许多会话可以获得同一个表上的共享锁.在一个表上放置共享锁的目的是为了防止另一个会话获得这个表上的排他锁(在已存在共享锁的情况下无法再获得排他锁).在表上防止排他锁是需要执行DDL语句.如果其他任何会话已经在一个表上放置了共享锁,那么我们就无法执行修改某个对象的语句(例如删除这个表的某一列).
为了在记录上执行DML语句,当前会话必须获取待更新记录上的排他锁以及包含这些记录的表上的共享锁.如果另一个会话已经获取了待更新记录上的排他锁,那么当前会话将被挂起,直至使用COMMIT或ROLLBACK命令解除这些锁定,如果另一个会话已经获取了待修改记录的表上的共享锁以及其他记录上的排他锁,那么就不存在任何问题.一个表上的排他锁会锁定这个表,但是,如果不需要执行DDL语句,那么我们就可以不锁定整个表的默认锁定机制.
提示:只有在特别请求并且编程人员具有充分理由的情况下,才可以要求在整个表上放置排他锁.
DML锁与DDL锁
所有DML语句都至少需要两种锁定:受影响记录上的排他锁,以及包含受影响记录的表上的共享锁.排他锁能够防止其他会话干预指定的记录,而共享锁则能够阻止其他会话使用DDL语句修改表的定义.这两种锁定会被自动请求.如果某条DML语句在指定记录上无法获取所需的排他锁,那么这条语句会被挂起直至获得所需的排他锁.
执行DDL命令需要使用所涉及对象上的排他锁.只有在针对指定表的所有DML事务结束,并且记录上的排他锁以及表上的共享锁都被解除之后,我们才可以获得执行DDL命令所需的排他锁,任何DDL语句所需的排他锁都是被自动请求的.但是,如果无法获取所需的排他锁(通常是因为其他会话已经获得用于DML语句的共享锁),那么DDL语句就会由于错误立即终止.
例子:
1. 使用SQL*PLUS,作为用户SYSTEM连接数据库.
2. 创建一个表,并且在这个表中插入一条记录.
>create table t1(c1 number);
>insert into t1 values(1);
>commit;
3.再次使用SQL*PLUS并作为用户SYSTEM进行连接,从而打开另一个会话.
4.在第一个会话中执行一个DML命令,这个命令会在插入的记录上放置一个排他锁,同时还会在创建的表上放置一个共享锁.
>update table t1 set c1=2 where c1=1;
5.如下所示,在第二个会话中执行第一条针对新建表的DDL语句.
>alter table t1 add(c2 date);
error at line 1:
ora-00054:resource busy and acquire with nowait specified
因为DDL语句需要表上的排他锁,而这与DML语句已在表上放置了共享锁相冲突,所以试图在表中插入一个列的这条DDL语句会失败.需要注意的是:在类似情况下,DML语句会等待并不断进行尝试,直至获得其所需的锁(换句话说就是挂起);而DDL语句则会由于错误立即终止.
6.在第一个会话中,提交当前事务
>commit;
7.在第二个会话中,重新执行步骤5.此时,因为不纯在与DDL排他锁相冲突的DML共享锁,因此DDL语句将成功的执行.
8.在第一个会话中 ,锁定整个表.
>lock table t1 in exclusive mode;
9.在第二个会话中,插入一条记录.此时,这个会话将被挂起.
>insert into t1 values (1,sysdate);
10.在第一个会话中,通过执行COMMIT命令解除整个表上的锁定.需要注意的是,ROLLBACK命令也可以实现相同的目的.
>commit;
11.第二个会话会释放并且现在会完成插入操作.随后,执行COMMIT命令,终止当前事务斌且解除该记录上的排他锁.
关于如何解决死锁的问题.
1.查哪个过程被锁
查V$DB_OBJECT_CACHE视图:
SELECT * FROM V$DB_OBJECT_CACHE WHERE OWNER=''过程的所属用户'' AND LOCKS!=''0'';
2. 查是哪一个SID,通过SID可知道是哪个SESSION.
查V$ACCESS视图:
SELECT * FROM V$ACCESS WHERE OWNER=''过程的所属用户'' AND NAME=''刚才查到的过程名
发表评论
-
mongo db 分片 副本集 权限配置
2014-10-23 16:15 749用户和认证 权限总结 : http://blog. ... -
no sql
2013-06-17 13:37 541Redis教程 命令集合: http://doc.re ... -
redis mogodb
2013-06-14 16:29 0nothing -
nosql
2013-06-13 23:05 0fdf -
mogoDB and Redis
2013-05-31 10:41 9Redis教程 http://violet84 ... -
mysql
2013-05-18 18:27 380mysql性能查询 http://blog.csdn.n ... -
noSql
2013-05-16 22:12 283http://robbin.iteye.com/blog/ ... -
Q4M queue for Mysql
2013-05-16 21:21 524http://blog.csdn.net/tianjing ... -
dbcp/jdbc比较
2013-05-15 22:47 622http://www.oschina.net/question ... -
索引原理算法
2013-05-12 21:28 509b树索引 http://my.oschina.net/l ... -
分库 分表
2013-05-12 14:06 500http://zhengdl126.iteye.com/b ... -
表分区
2013-05-06 13:09 344http://space.itpub.net/219982/v ... -
DECODE函数的性能
2011-10-12 10:21 995文章转自:http://dingchaoqun12.blog. ... -
procedure存储过程 返回数组
2011-10-10 10:13 929文章转自:http://oracle.chinaitlab.c ... -
mysql分页
2011-07-23 11:29 746转自: http://www.phpweblog.net/pe ... -
Oracle中Decode()函数使用技巧
2011-06-23 22:23 632DECODE函数是ORACLE PL/SQL是功能 ... -
SQL游标原理和使用方法
2011-06-23 22:21 944转自:http://www.knowsky.com/34407 ... -
Oracle 中 decode 函数用法
2011-06-23 22:19 832作者:ZHF 出 ... -
种可以避免数据迁移的分库分表scale-out扩容方式
2011-06-23 22:16 1174转自:http://rdc.taobao.com/ ... -
Oracle 10g RAC的负载均衡配置
2011-06-23 22:14 829转自:http://www.cnblogs.com ...
相关推荐
在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁(用来保证表的结构不被用户修改),TX锁称为事务锁或行级锁。当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统...
关于oracle锁以及并发的详细描述。
oracle锁机制研究
详细介绍了Oracle中各种锁的机制原理及解锁方法
Oracle数据库多粒度锁机制介绍概述.内容简单易懂,容易掌握
Oracle的锁机制,访问数据时,保证数据读的一致性、数据的完整性和数据的并行性的一种机制
oracle数据库锁机制常备大家所诟病,希望对学习者有帮助,大家自觉学习
介绍在oracle数据库中锁的使用和运行方式
数据库是一个多用户使用... 在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被
(这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率)TM锁分类:共享锁(S锁)、排它锁(X锁)、
oracle并发和锁机制,oracle并发锁,oracle锁
Oracle数据完整性和锁机制
Oracle的锁机制归纳总结,该文档详细介绍了各种档的使用方法和优缺点
想深入了解oracle锁机制,这篇文章足已,不信下了就知道,本人看了这篇文章,受益良好。
有关于Oracle 10g 关于锁方面的概念和演示
本文通过对Oracle数据库锁机制的研究,首先介绍了Oracle数据库锁的种类,并描述了实际应用中遇到的与锁相关的异常情况,特别对经常遇到的由于等待锁而使事务被挂起的问题进行了定位及解决,并对死锁这一比较严重的...
理解ORACLE数据库锁机制高效维护医院信息系统运行.pdf