关于数据库意向锁与封锁粒度若干问
我们所说的加锁是谁对谁加锁?
是事务T对某个封锁对象加锁。封锁对象的大小被称为封锁的粒度,这个对象可以是数据库、关系,也可以是元组。
为什么要引入多粒度锁协议?
封锁粒度大,系统被封锁的对象越少,并发度越小,系统开销越小。
封锁粒度越小,系统被封锁的对象越多,并发度高,系统开销大。
必须要在系统开销和并发度进行权衡,以求得最佳效果。所以,要引入支持多种并发控制粒度的并发协议,多粒度锁协议。
为什么会有显式封锁和隐式封锁?
多粒度树中的每个结点都可以被独立的加锁,对这种结点的封锁被称为显式封锁,对一个结点加锁意味着这个结点的所有后裔结点也被加了同样类型的锁,这些后裔结点的封锁方式就是隐式封锁。
为什么要引入意向锁?
在没有意向锁的时候,事务要对某个数据对象加锁,要检查这个对象上有没有显式或隐式的封锁与之冲突;还要检查上级结点,因为上级结点显式加锁后,其子结点会被隐式加锁;还要检查所有的下级结点,看下级结点有没有显式封锁和即将加到下级结点的隐式封锁冲突。以一个表加锁为例,如果要加R锁,就要检查它的每一个元组,也就是子结点有没有加上与之不相容的锁,这样效率很低。既要检查上级又要检查下级,所以就要引入意向锁。
意向锁的优势?
要知道,锁与意向锁是不同的概念。锁R共享锁、X排它锁。意向锁IS、IX、SIX。
引入意向锁后,在检查相容时,只需要从粒度树的根结点检查到某个要加锁的结点即可,不用检查其子结点。这是因为如果某对象已经加锁,他的上层结点必然加了意向锁。对某个结点加了意向锁,他的后裔结点必然加了锁。
如何解释锁的相容矩阵?
两个事务对同一个对象加锁,用锁相容矩阵判断是否可以加锁。注意,是两个事务,而不是一个事务。通过几个例子来理解这个图
首先解释SIX锁是什么。SIX锁是事务T对同一个结点加了S锁和IX锁,意味着T要读这个数据对象,并且会修改某些后裔结点代表的对象。注意,一定是同一个事务中才可以这样加锁,两个不同的事物要对某结点分别加S锁和IX锁就会不相容。
例1、
T1加S锁,表示数据的子节点都是隐式的加了 S 锁
- T2 加 S 相容,因为都是读锁
- T2 加 IS 相容,后裔某个结点加了读锁
- T2 加 IX ,不相容,因为某结点加了IX之后,后裔结点必然有加X锁,但这个结点已经加了S锁,其后裔结点会隐式加S锁,X锁与S锁冲突。
- T2 加 SIX, 不相容,SIX=S+IX,参考上一条
- T2 加 X ,不相容, S和X冲突
例2、
T1加X锁,
- T2不能加任何锁或意向锁。
例3
T1加IS锁
-
T2不能加X锁。
-
T2 加 IX锁 相容。因为只是意向锁。例如某个关系R加了IS和IX,下级结点元组1加了R锁,元组2加了X锁,不冲突。
例4
T1加IX锁,
- T2不能加S,X,SIX锁,参考上面的内容。
例5
T1加SIX锁,
- T2只能加IS锁。不能加S,X,IX,SIX锁。
事务T遵循的对多粒度树结点Q的加锁规则:
必须遵循锁相容矩阵;
粒度树的根必须首先被加锁,锁的类型不限;
当Q的父节点被T加上IX或IS时,Q才可以被T加上S或IS型锁。
当Q的父节点被T加上IX或者SIX,Q才可以被T加X、SIX或IS锁。
当T还没有释放任何锁,T才可以对结点加锁
当Q的所有后裔结点都不被T加锁,T才可以解锁Q。