标签:style blog http os 使用 strong ar for 文件
层次锁,更多地是在数据库设计中被提到,但也有少数分布式锁系统也实现这个概念。下面内容主要还是从数据库设计的角度来理解层次锁的概念。
粗略说来,当执行SQL语句时数据库都会开启事务,在SQL执行完毕commit时,会把所有受影响数据写到磁盘文件并结束事务。在事务执行期间,为了保证事务的ACID,SQL所影响到的表、行等数据都会被不同程度的进行锁定,我们笼统称为“事务锁”。从使用者的角度来看,一般数据库都提供了表锁和行锁,其中行锁要比表锁粒度要细很多,被认为是支持高并发事务的关键。
但仅靠表锁和行锁是不够的,比如一个事务进行了行锁定,而另一个事务需要表锁定,那如何判断表锁定是否可以成功?同样,一个事务锁定了某些行,而另一事务需要读取这些行,是否允许读取?当考虑到不同的数据库操作和隔离级别时,锁的实现会变得非常复杂。
有一个关键问题是,数据库锁用来锁什么,从数据库实现上来说是锁数据库内部的数据库结构,因为各数据库实现不一,因此锁的内容也就有所区别。对Oracle来说存在表、行、回滚段、Redolog等结构;SQLServer存在表、页、行等结构,这些结构在逻辑上存在上下级关系,比如SQLServer中,每个表的数据有多个页构成,而页中有包含了多行的内容,而一般认为行没有下级数据结构,为事务操作的最小单位。既可以对表,也可以对页、行对象加锁,抽象一点,称这些能加锁的对象为Node。
数据库中存在下面类型的锁:
上面三种锁是描述了某个Node被修改时的锁类型,但因为Node存在上下级关系,但Node被加锁时,我们需要评估上级Node的加锁情况,比如当给行加各种锁的时候,表的加锁情况是神马?
之所以这样做的原因是因为存在一个需求:
若逐行去检查,在数据量非常大的时候性能会有巨大的损伤,因此引入一种能描述表被加锁情况的锁类型---意向锁。当程序对Node进行加锁操作时,需首先声明上级Node的锁类型。比如,对行加排他锁之前需对表加意向排他锁。
这样事务A在更新数据之前会对表加意向排他锁,而事务B在加排他锁之前发现A加的意向排他锁,所以必须等待A完成,从而避免了逐行检查的问题。
从下层节点来说,意向锁是对所有下级Node加锁情况的整体说明;但从上层Node来说,意向锁描述的是其下层Node正在被加某种锁(比如排他锁),或说下层Node有加某种锁的意向,这样正是“意向"一词的由来。
意向锁与共享锁、排他锁、共享锁不同的时,只能加在存在下级Node的Node对象上,比如可以加在表、页上,但不能加在行上,因为行是事务加锁的基本元,不存在有”意向“的下级Node。
意向锁具体有分:意向共享锁(Intent Share)、意向排他锁(Intent Exclusive)、共享意向排他锁(Share Intent Exclusive),下面逐一说明
因为对同一Node可能存在多个事务期望对该Node加不同的锁,这就需要列出锁直接的相容性,只有相容的锁才允许被同时加在同一Node上,否则后面事务就需要等待。
下表直接引用自微软网站:http://msdn.microsoft.com/en-us/library/aa213041(v=sql.80).aspx
Existing granted mode | ||||||
---|---|---|---|---|---|---|
Requested mode | IS | S | U | IX | SIX | X |
Intent shared (IS) | Yes | Yes | Yes | Yes | Yes | No |
Shared (S) | Yes | Yes | Yes | No | No | No |
Update (U) | Yes | Yes | No | No | No | No |
Intent exclusive (IX) | Yes | No | No | Yes | No | No |
Shared with intent exclusive (SIX) | Yes | No | No | No | No | No |
Exclusive (X) | No | No | No | No | No | No |
因为意向锁的引入,导致锁之间也存在上下级关系:比如表的锁为SIX、页的锁为:IX、行的锁为:X,这样对某个Node及下级Node来说,存在着层次锁的概念,也即多粒度锁。
各事务可以使用不同粒度的锁与Node及其下级Node进行交互,从而提高事务的并发性。
还有一类锁,在SQLServer中称为“区间锁”(Key-Range),在Mysql中称为”间隙锁“(Gap Lock),主要应对下面场景:
假如事务执行:SELECT * FROM T WHERE ID>10 AND ID<20,在READ_REPEATABLE的隔离级别下,无论事务执行都少次都希望能返回相同的结果,也即不能在10<ID<20之间更新任何数据,这就需要锁住(10,20)这个区间,这便是区间锁的由来。
与上面列出的锁类型不同的是,这类锁物理上并不存在,只是有前面几种锁类型组合出的逻辑锁。
在Oracle、SQLServer中,当行锁多到一定的程度后,为了降低锁带来的开销,数据库引擎会把行锁升级为表锁(或页锁),但在Mysql中不存在这个问题,因为Mysql说他们的行锁算法极度节省空间。
本文主要罗列了一些数据库锁的概念,这些概念中有些并不通用,不是在所有数据库中都存在,主要目的是为了因此层次锁的概念,层次锁的实现在各数据库中也差异很大。
层次锁的优点是可以通过多粒度锁的方式锁定对象,从而为高并发带来极佳的性能。
转自:http://blog.csdn.net/chen77716/article/details/7214132
【参考资料】
标签:style blog http os 使用 strong ar for 文件
原文地址:http://www.cnblogs.com/javaleon/p/3945875.html