• DB2锁机制


        相比较Oracle来说,DB2的锁机制麻烦了很多,而且这个麻烦带来的不是性能的上升而是下降,
    不过如果细致了解的话,只能感慨不愧是数据库理论诞生的公司,在实现数据库理论上比Oracle全面得多。
        Oracle没有实现一般数据库理论里的锁机制,带来的并发性与性能上的提升以及相关的问题上文已经介绍了,
    现在来说说几乎完全实现一般数据库理论锁机制的DB2数据库这方面的实现。
        下面的资料来源于IBM资料库DB2和 Oracle的并发控制(锁)比较
        首先是锁是属性,有如下几个基本属性:锁定对象,锁定大小,锁定时间,锁定状态。
    锁定对象表示锁定的数据资源,DB2支持对表空间,表,行,索引(大型机里支持对数据页)的锁定。通常考虑表锁与行锁。
    锁定大小表示锁定的数据大小。
    锁定时间通常由事务的隔离级别控制。
    锁定状态就是锁的类型,下面将会介绍。
    表 1:DB2支持的表级锁定
    名称缩写     全名                                    描述
    IN           无意图锁(Intent Node),不需要行锁     拥有者可以读取包括其他事务未提交数据在内的所有数据,但不能对表中的数据作出修改
    IS       意图共享锁(Intent Share),需要行锁配合    拥有者可以在拥有相应行上的S锁时可以读取该行的数据,但不能修改数据
    IX   意图排他锁(Intent eXclusive),需要行锁配合    拥有者可以在拥有相应行上的X锁时可以修改该行的数据
    SIX 共享并且意图排他锁(Share with Intent eXclusive),需要行锁配合   拥有者可以读取表中的任何数据,如果在相应的行上可以获得X锁,可以修改该行。SIX的获取比较特殊,当程序拥有IX锁时请求S锁,或者在已经拥有S锁的时候请求IX锁时产生
    S                 共享锁(Share),不需要行锁配合    可以读取表上的任何数据,如果表上被加了S锁,表上的数据只能被读取而不能做出任何修改
    U                更新锁(Update),不需要行锁配合    拥有者可以读取表中的任何数据,如果升级为X锁,则可以更改表中的任何数据,该锁是等待对数据进行修改的一种中间状态
    X             排他锁(eXclusive),不需要行锁配合    拥有者可以读取或者修改表中的任意数据,如果加上了X锁,除了未提交读事务外,其他程序都不能对表进行任何读取或者修改
    Z   超级排他锁(Super eXclusive),不需要行锁配合    该锁一般不是由DML产生,而是由Drop,Alter或者创建删除索引时产生的,加上Z锁后,所有程序(包括未提交读程序)都不能对表进行读取或者修改
    具体来说,IS,IX,SIX用于表一级并且需要行锁配合,用于阻止其他程序对表加上排他锁。区别如下:
    ·  如果一个程序获得表的IS锁,程序可以获得某一行上的S锁用于只读操作,其他程序也可以读取该行,或者对表中其他行作出修改。
    ·  如果一个程序获得表的IX锁,程序可以获得某一行的X锁用于更改操作,其他程序可以更改或者读取表中其他的行。
    ·  如果一个程序获得表的SIX锁,程序可以获得某一行的X锁用于更改操作,其他程序只能对表中的其他行进行只读操作。
    S,U,X,Z用于表一级,不需要行锁的配合。区别如下:
    ·  如果程序得到表的S锁,则程序可以读表中的任意数据,同时允许其他程序获得表上的只读锁请求,如果有程序需要更改表上的数据,必须等到S锁释放。
    ·  如果程序得到U锁,程序可以读取表中任意数据,最终可以通过获得X锁得到对表中任意数据的修改权,其他程序只能读取表中的数据,U锁与S锁的区别在于修改意图,U锁的设计主要是为了避免两个程序在拥有S锁的情况下同时申请X锁导致死锁。
    ·  如果程序得到表上的X锁,程序可以读或者修改表上任意数据,其他程序无法读或者修改表上的数据。
    ·  如果程序获得Z锁,程序可以读或者修改表中任意数据,其他程序包括未提交读程序在内不能对表执行读或者修改操作。
    IN锁用于表上以允许未提交读这一概念。
    DB2支持的行锁如下所示:
    名称缩写      全名               需要表锁最低级别                 描述
    S           共享锁(Share)         IS                            该行正在被读取,其他程序只能执行读操作
    U           更改锁(Update)        IX                            某个程序正在读取并有可能修改该行,其他程序只能读取该行
    X           排他锁(eXclusive)     IX                            该行正在被某个程序修改,其他程序不能访问该行
    W    弱排他锁(Weak eXclusive)     IX                            一行被插入表后,该行会加上W锁,只有锁的拥有者可以修改该行,与X锁的不同在于该锁与NW锁兼容
    NS   下一键共享锁(Next Share)     IS                            拥有者与其他程序都可以读取该行,但不能进行修改,当程序处于RS或者CS隔离级别下时,该锁可以代替S锁
    NX  下一键排他锁(Next  eXclusive) IX                            一行的数据被插入到索引或者从索引被删除时,该行的下一行会被加上NX锁,锁的拥有者可以读该行的数据但不能修改。该锁与X锁类似,但与NS锁兼容
    NW  下一键弱排他锁(Next  Weak eXclusive) IX                     一行的数据被插入到索引时,该行的下一行会被加上NW锁,锁的拥有者可以读但不能修改该行的数据,与X锁及NX锁类似,但与W锁以及NS锁兼容
    默认情况下,DB2总是尝试获取行锁,但可以使用ALTER TABLE语句修改为总是获取表锁,也可以使用LOCK TABLE语句获取表锁。
        以上就是DB2复杂的锁机制,相比较Oracle,DB2没有做任何乐观假设,写必须阻塞读,读必须阻塞写,不然会影响读一致性,这是最正统的数据库理论。
    不过对于开发人员来说,这种锁机制就是一个噩梦,在写任何并发性程序之前,首先就是要分析锁,我前后用了两天才理顺DB2里各种锁之间的关系,话说,
    如果可以理解上面两张锁阻塞表,估计就可以对DB2锁机制有一个清醒的认识了。
        下面是DB2的事务隔离级别,话说我一直以为只有事务级与语句级隔离级别,直到我看了DB2的事务隔离级别。
        首先是可重复读(RR-RepeatableRead)级别,这一级别怎么说呢,概括一点,这个级别会锁定所有使用到的表,直到事务结束,
    保证事务开始一直到结束所可能需求的数据没有任何变化。即事务运行时,其他程序无法修改其所用到的表,
    这一级别类似oracle的事务级隔离级别,但Oracle没有锁定表,只是假定没有人去修改所需求的数据。
        下一个是读稳定性(RS-ReadStability)级别,这一级别只锁定真正使用到的行(包括修改的行以及检索到的行),而且可以读到其他已提交事务的数据。
        在往下是游标稳定性(CS-CursorStability)级别,这一级别类似Oracle的语句级隔离级别,锁定的只有修改了的行,可以读取已提交事务的数据。
        最后是未提交读(UR-UncommittedRead)级 别,这一级别如题,可以读到未提交的数据,不过如果修改了数据,则其表现与CS相同,即锁定修改了的行防止别的会话修改。
        四个事务级别,确保所有可能需要的数据不要被人修改->确保已经读取的数据不要被人修改->确保修改的数据不要被别人修改->可以读取别人未提交的数据(修改的数据同样不允许被别的程序修改)。

    下一个讨论的是锁转换。
        当程序向数据库请求它已经加锁的对象上面的锁的时候,数据库会比较对象上现在的锁与所请求的锁的模式,如果所请求的锁级别更高,则把现在的锁升级为请求的锁。
        锁级别比较:
        表锁:IN<IS<S<IX<U<X<Z
        行锁:S<U<X
        有一个特殊例子是,如果持有S锁请求IX锁,或者持有IX锁请求S锁,锁转换结果为SIX锁。
        下面来谈谈DB2里著名的锁升级问题。
        在学Oracle的时候,我从来不知道锁升级这个概念,这是由于Oracle中,锁并不是稀缺资源,没必要把多个锁合并为同一个锁来减少资源占用。
        DB2里有两个参数,LOCKLIST与MAXLOCKS,LOCKLIST表示数据库分配的用来储存锁列表的空间大小,MAXLOCKS表示程序最大允许占用锁列表大小的百分比,
    当超过这个百分比的时候,就会进行锁升级,这里我就不发那长长的一大串DB2锁列表计算公式了,只需要知道,DB2会在一个程序锁定过多行的时候,
    会把锁定多行变更为锁定整个表。这是一个Oracle里没有的概念,如果从Oracle转为DB2,需要注意。
        最后说说锁等待,这里类似Oracle里的nowait选项,DB2里面有一个参数LOCKTIMEOUT,可以设置这个参数的值来设定遇到锁阻塞后的等待时间,如果超时的话就会回滚语句。
        在DB2的开发建议里,为了实现并行化与数据完整性,有如下几个建议,比较Oracle的类似建议的话,相当有意思。
    ·  频繁使用commit来使多个用户可以并发地访问数据(Oracle中的建议是尽可能维护业务事务的完整性,而不是切割成小事务)
    ·  发出commit语句前,关闭CURSORWITH HOLD来确保所有锁都得到释放(Oracle中事务提交或者回滚后自动解锁,不需要其他操作)
    ·  指定适当的隔离级别。DB2会借助一切机会锁定行,需要不同的隔离级别来协调(Oracle在必要的时候使用事务级隔离,一般只需要语句级隔离级别)
    ·  适当使用LOCKTABLE语句(尽可能不要使用也很少有必要使用LOCL TABLE语句)
    DB2的开发建议还有很多,感兴趣的可以去看看相关资料,与Oracle的开发建议比较相当有意思的。
    关于两个数据库锁与并行的介绍就到这里,这篇文章中没有介绍DB2并发性的问题,但其实也没必要介绍,在锁机制部分已经到达并发性的瓶颈,并发性在DB2的锁机制下受到的限制太大了。

  • 相关阅读:
    web接口调用
    UISegmentedControl
    CocoaPods安装和使用教程
    NSTimeInterval
    OC-NSString从文件中读取字符串
    XMPP(mac)方案二 ejabberd 服务器搭建 (转载)
    监听 IOS响应式编程框架ReactiveCocoa(RAC)使用示例(转载)
    iOS开发-文件管理
    OC中NSString 的常用方法 (转载)
    NSAttributedString
  • 原文地址:https://www.cnblogs.com/BradMiller/p/3197906.html
Copyright © 2020-2023  润新知