zoukankan      html  css  js  c++  java
  • 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#' 语句来杀死会话,强行解决锁争用。

  • 相关阅读:
    java实验二
    实验1
    响应式站点设计之使用指南
    掌管一个网站?给你九条忠告
    在本地App上设计Web代码
    订阅
    下载站焦点图
    个性化电影频道js
    展开收起播放列表
    onoff组件
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5320529.html
Copyright © 2011-2022 走看看