Oracle中的锁

     Oracle数据库支持多个用户同时与数据库进行交互,每个用户都可以同时运行自己的事务,从而也需要对并发访问进行控制。Oracle也是用“锁”的机制来防止各个事务之间的相互影响,对并发访问进行控制的,保证数据的一致性和完整性。当一个事务或操作企图防止另一个事务对其操作的对象产生影响时,该事务或操作就对该对象进行锁定,其他事务就只能在该事务释放锁之后才能操作该对象。

     在大多数情况下,锁对于开发人员来说是透明的,不用显式地加锁,即不用指定锁的分类、级别、类型或模式。如,当更改记录时,Oracle会自动地对相关的记录加相应的锁;当执行一个PL/SQL过程时,该过程就会自动地处于被锁定的状态,允许其他用户执行它,但不允许其他用户采用任何方式更改该过程。当然,Oracle也允许用户使用Lock Table语句显式地对被锁定的对象加指定模式的锁。

     锁有2种最基本、最简单的类型:排他锁(eXclusive lock,即X锁)、共享锁(Share lock,即S锁)。这两种锁及其锁定的示意图如下图所示。该图中显式了不同的锁的作用,以及相互之间的相容规则。

  

                                 

    排他锁又称为写锁。如果事务T在数据库对象A上加了X锁,则只允许T读取、更改A。其他任何事务Ti都既不能对A加S锁也不能加X锁,直到T释放A上的X锁为止。这就保证了其他事务Ti在事务T释放A上的X锁之前,不能再读取、更改、使用A,即保护A不被同时地读、写。

    共享锁又称为读锁。如果事务T在数据库对象A上加了S锁,则只允许T读取A但不能更改A。其他任何事务Ti都只能对A加S锁而不能加X锁,直到T释放A上的S锁为止。这就保证了其他事务Ti在事务T释放A上的S锁之前,只能读取A但不能更改A,即保护A不被同时地写。

锁除了对操作进行限制外,锁对锁也进行限制,排他锁与共享锁的相容规则如表所示。

                                      

                                 

              

   

一、锁定的粒度与意向锁

    锁定对象的大小被称为锁定的粒度(granularity)。锁定对象可以是逻辑单元(如数据库、表、记录、列、索引等),也可以是物理单元(如数据页、索引页等)。

锁定的粒度与系统的并发度和并发控制的开销密切相关。一般地,锁定的粒度越大,需要锁定的对象就越少,可选择性就越小,并发度就越小,开销就越小;反之,锁定的粒度越小,需要锁定的对象就越多,可选择性就越大,并发度就越大,开销就越大。

    例如,如果锁定的粒度是表,事务T1需要操作表A中的记录r1,则T1必须对包含记录r1的表A加锁。在T1对A加锁之后,事务T2需要操作表A中的记录r2,因此就需要对表A加锁,但此时因为T1已经在表A上加了锁,所以T2的加锁就会失败,就被迫等待,直到T1释放锁为止,事务T1和T2就不能并发执行了;如果锁定的粒度是记录,则事务T1可以对表A中的记录r1加锁,同时事务T2也可以对表A中的记录r2加锁,所以事务T1和T2就可以并发执行了,并发度就增大了,但维护这个并发度就需要更多的开销了。

 

1、多粒度锁定与多粒度树

    如果在一个数据库管理系统中,同时支持多种锁定粒度供事务选择,这种锁定方法就被称为多粒度锁定(multiple granularity locking)。

    如下图所示是一个四级的多粒度树。该树的根节点是数据库,表示最大的粒度;页节点是列,表示最小的粒度。

                      

 从前面的例子可知,选择锁定粒度时应该同时考虑并发度与开销两个因素。以求最优的效果。一般地,需要处理大量记录的事务可以以表为锁定粒度;需要处理多个表中的大量记录的事务可以以数据库为锁定粒度;而只需要处理某个表中少量记录的事务,则可以以记录为锁定粒度。

    多粒度锁定协议是指,允许对多粒度树中的节点单独地加锁,另外,对一个节点加锁还意味着对这个节点的各级子节点也加同样的锁。   

    因此,可以用两种方法对多粒度树中的节点加锁:显式锁定、隐式锁定。显式锁定是在事务中明确指定要加在节点上的锁;隐式锁定是由于在其上级节点中加显式锁时而使该节点获得的锁。

在多粒度锁定中,显式锁定与隐式锁定的作用与相容规则都是一样的。因此,当系统检查锁定的冲突时,不仅要检查显式锁定还要检查隐式锁定。

    一般地,当对一个节点加锁时,系统第一要检查在该节点上有无显式锁定与之冲突;第二要检查其所有上级节点有无显式锁定与之冲突,以便查看在该节点上加该显式锁定,是否会与从上级节点获得的隐式锁定有冲突;第三要检查所有下级节点有无显式锁定与之冲突,以便查看在该节点上加该显式锁定,是否会使下级节点从该节点获得的隐式锁定与其显式锁定有冲突。

    这种检查锁定冲突的方法的效率很低,所以引进了意向锁(Intended lock)的概念。

 

2、意向锁

    意向锁的含义是,如果对一个节点加某种意向锁,则会对该节点的各级下级节点加这种锁;如果对一个节点加某种锁,则必须先对该节点的各级上级节点加这种意向锁。

例如,对记录r1加锁时,必须先对它所在的表A加意向锁。于是,事务T1对表A加X锁时,系统只需要检查根节点数据库D和表A是否已经加了不相容的锁,而不再需要检查表A中每个记录是否加了X锁。

有如下几种意向锁。

    一、IS锁(Intended Share lock,意向共享锁)

    如果对一个节点加IS锁,则表示对它的所有下级节点有加S锁的意向;如果对一个节点加S锁,则必须先对该节点的各级上级节点加IS锁。

    二、IX锁(Intended eXclusive lock,意向排他锁)

    如果对一个节点加IX锁,则表示对它的所有下级节点有加X锁的意向;如果对一个节点加X锁,则必须先对该节点的各级上级节点加IX锁。

    三、SIX锁(Share Intended eXclusive lock,共享意向排他锁)

    如果对一个节点加SIX锁,则表示对它加S锁,然后再加IX锁,即SIX=S+IX。例如,如果事务T对表A加SIX锁,则表示事务T要读取整个表(S锁的作用),同时还会更新某些记录(IX锁的作用)。

包括意向锁的各种锁之间的相容规则如表所示。

          

例如,当事务T对表A保持的锁是S锁时,事务Ti不可以获得对表A的IX锁,但可以获得对A的IS锁。所以S锁与IX锁的强度相当,但比IS锁的强度要强。

    同上理,可以逐个地推导出这些锁的强度关系,如图所示。图中上面的锁比下面的锁的强度要强,同级的锁强度相当。一个事务在申请锁定时以强锁代替弱锁是安全的(但会降低并发度),反之则不然。申请锁定时应该按自上而下的次序进行,释放锁定时则应该按自下而上的次序进行。

具有意向锁的多粒度锁定方法能提高系统的并发度,减少加锁和解锁的开销,已经在实际DBMS中得到应用,如Oracle数据库。

 

二、锁的分类

    Oracle主要有2种锁:DDL锁(字典锁)、DML锁(数据锁)。

1 DDL

    当用户发布DDL(Data Definition Language)语句时会对涉及的对象加DDL锁。由于DDL语句会更改数据字典,所以该锁也被称为字典锁。

    DDL锁能防止在用DML语句操作数据库表时,对表进行删除,或对表的结构进行更改。

    对于DDL锁,要注意的是:

    $$ DDL锁只锁定DDL操作所涉及的对象,而不会锁定数据字典中的所有对象。

    $$ DDL锁由Oracle自动加锁和释放。不能显式地给对象加DDL锁,即没有加DDL锁的语句。

    $$ 在过程中引用的对象,在过程编译结束之前不能被改变或删除,即不能被加排他DDL锁。

    DDL锁的类型与特征如表所示。

   

      DDL锁很少会在系统里引起争用,因为它们的保持时间都非常短暂。但DDL锁的存在却不容忽视,尤其是在申请排他DDL锁时。

2、DML

当用户发布DML(Data Manipulation Language)语句(如insert、update、delete)时会对涉及的对象加DML锁。由于DML语句涉及的是数据操作,所以该锁也被称为数据锁。

DML锁能防止多个事务并发访问数据时,对数据的一致性和完整性的破坏。

根据锁定的粒度和意向,DML锁有几种模式。在执行Lock Table语句或执行不同的DML语句时会加不同模式的DML锁。当一个事务在一个表上加了某种模式的DML锁之后,另一个事务在该表上所能执行的DML操作会受到限制,如下表所示。其中有的锁模式有2个名称,这是因为不同的Oracle版本在提到它们时使用了不同的表示方法。

三、死锁现象及其解决

    死锁是一种比较严重的、特殊的锁争用类型。在这种锁争用中,两个或两个以上的用户正在等待对方锁定的资源。因此,如果不进行某种干预,任意一个事务都无法完成。

假设当前有两个会话,分别执行的事务如图所示。显然这两个会话之间由于互相锁定了对方所需要锁定的对象,所以发生了死锁。

    “提示”Oracle提供了有效的死锁检测机制,周期性地(通常只有几秒钟)诊断系统中有无死锁,并提示用户。

当Oracle检测到死锁后,会在预警文件和跟踪文件中记录下死锁的信息,在跟踪文件中详细地记录了检测到死锁的时间、被死锁的语句、阻塞者会话、等待者会话、操作系统用户的信息(如用户名、用户所在的计算机、用户使用的应用程序)等有助于确定死锁及其处理方法的信息。

即使Oracle为会话A提示了检测到死锁的信息,并且回退了会话A的第2个update语句,但会话A仍然在第1个update语句上保持着锁,并阻塞了会话B的第2个update语句.

    当出现检测到死锁的信息后,用户自己(或DBA通知相应的用户)执行commit语句或rollback语句,使事务结束,释放所加的锁。还可以使用 ALTER SYSTEM KILL SESSION 'sid, serial#' 语句来杀死会话,强行解决锁争用。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Oracle,要解住的表,可以按照以下步骤进行操作: 1. 首先,查看数据库,诊断的来源及类型。可以使用以下SQL语句查询信息: SELECT OBJECT_ID, SESSION_ID, LOCKED_MODE FROM V$LOCKED_OBJECT; \[1\] 2. 找出数据库的serial#,以备杀死。可以使用以下SQL语句查询被住的会话信息: SELECT T2.USERNAME, T2.SID, T2.SERIAL#, T2.LOGON_TIME FROM V$LOCKED_OBJECT T1, V$SESSION T2 WHERE T1.SESSION_ID = T2.SID ORDER BY T2.LOGON_TIME; \[2\] 3. 根据步骤2查询到的会话信息,使用以下SQL语句杀死该会话: ALTER SYSTEM KILL SESSION 'sid,serial#'; (其sid和serial#为步骤2查询到的值)\[2\] 此外,还可以使用以下SQL语句查看哪个表被: SELECT b.owner, b.object_name, a.session_id, a.locked_mode FROM v$locked_object a, dba_objects b WHERE b.object_id = a.object_id; \[3\] 请注意,解表需要谨慎操作,确保只解正确的会话和表。 #### 引用[.reference_title] - *1* *3* [Oracle数据库表被如何查询和解详解](https://blog.csdn.net/qq_46071165/article/details/130104761)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Oracle表被住及解方法](https://blog.csdn.net/u012934325/article/details/81015484)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值