基于封锁的并发控制机制
锁的概念及封锁的原理
- 锁的基本模式
- 共享锁( Shared---S锁):允许执行读操作
- 排它锁( Exclusive---X锁):允许执行读/写操作
- 锁的调度策略
- 解除一个数据对象的排它锁之前,其它事务不能对它加任何锁
- 一个数据对象允许加几个共享锁,但不能在共享锁之上,加排它锁
- 锁的相容矩阵
例:两个事务对A和B进行读写操作,可以进行加锁,事务1先申请数据AB上的X锁,事务2对数据AB进行读操作,所以申请S锁。T1T2都在同一时间内对数据AB进行操作,由于T1先加锁,T2后加锁,再根据锁的相容矩阵原理,T2的读操作要等到T1解锁之后才能进行。这就强制使得T1T2在对数据AB的操作上执行串行操作。这就是通过锁来实现并发控制。
- 随意加锁容易产生问题
-
不正确加锁产生错误结果:
- T1对数据AB执行完后,T2得出的A+B的值应该是不变的,但是由于没有控制的加锁,当T1T2并发执行时,T2得出的A+B的值将不正确。所以随意加锁虽然可以控制两个事务对数据的进行操作的冲突,但是显然容易产生不正确的结果。
-
产生死锁现象:
- 两个事务均在等待对方进行解锁操作,于是产生死锁现象。
- 两个事务均在等待对方进行解锁操作,于是产生死锁现象。
-
产生饿死现象:
-
T1先对数据A加了S锁,然后进行读操作,此时T2想对数据A进行读写操作,加X锁,但是要等T1解锁,之后T3也对数据A进行读操作,加了S锁,于是T2就处在不断等待的过程中。
-
-
两阶段锁协议
两阶段锁协议:所有事务分两个阶段提出加锁和解锁请求。
- 增长阶段:事务可以获得锁,但不能解锁;
- 缩减阶段:事务解锁,但不能获得锁。
- 遵循了两阶段锁协议的并发控制算法所产生的调度是冲突可串行调度。即解决了第一个问题,但仍然存在死锁现象,级联回滚可能发生。
-
如果在某一时刻T1产生故障就会导致T2和T3读到脏数据,T1如果回滚。T2和T3也会发生回滚,就会存在一个级联回滚现象。 - 避免级联回滚的方法:严格两阶段锁协议——要求事务所持有的X锁(排它锁)必须在事务提交之后才能释放。
强两阶段锁协议:要求事务提交之前不得释放任何锁。比严格两阶段锁协议更严格。
- 大部分数据库系统采用严格两阶段锁协议或强两阶段锁协议。
- 但这两种协议并行程度较低,有时为提高并行能力,采用锁转换机制,在写的时候将S锁转换成X锁,写完后再降为S锁。
-
例如T1要对数据进行读写操作,T2要对数据进行读操作,T1并不是一开始就对数据进行X锁,而是先进行S锁,可以方便T2同时进行读操作,当T1要进行写操作的时候才将S锁升级为X锁,写完后又将X锁降为S锁。通过这样的方式提高T1T2的并发程度。如下图: -
多粒度锁及意向锁
多粒度树:
多粒度加锁的特点:
- 显式加锁:树上每个结点都可以单独加锁
- 隐式加锁:对当前结点加锁会导致隐式地对全部后代结点加上同类型的锁。
检查锁冲突时,必须检查祖先、后代结点。
对锁类型进行扩充:
- 意向锁:一个事务对一个数据对象显式加锁之前,必须对它的全部祖先结点加意向锁。如果一个结点上有意向锁,则它的后代结点必有被显式加锁。
意向锁分类:
- IS锁(Intent Share Lock):若对某结点加IS ,那么将对后代结点显式地加S锁。
- IX锁(Intent Exclusive Lock):若对某结点加IX锁 ,那么将对后代结点显式地加X锁。
- SIX锁(Share Intent Exclusive Lock):若对某结点加SIX锁,则对该结点不仅显式地S锁,而且还对它加了IX锁。即, SIX= S + IX
锁类型的相容性矩阵:
可串行性多粒度锁协议:
- 必须遵守锁类型的相容性矩阵。
- 根结点必须首先加锁。
- 任何事务都必须遵守两阶段锁协议。
- 任何事务加锁都必须按从根到叶子顺序进行。
- 任何事务开锁都必须按从叶子到根顺序进行。
例: T1想对r1进行读操作,就要对r1的父节点及所有祖先节点加上意向共享锁IS,然后对r1加S锁;T2想对r2进行写操作,就要对r2节点的父节点及祖先节点加上意向写锁IX,然后对r2加写锁X;T3想对Da进行读操作,就要对Da的父节点及所有祖先节点加上意向共享锁IS,然后对Da加S锁。
多粒度锁协议的优点:增加并行性,减少锁开销。
多粒度锁协议在由如下事务类型混合而成的应用中有用:
- 只存取几个数据项的短事务
- 由整个文件或一组文件形成报表的长事务
锁管理器:封锁机制的实现是由锁管理器执行,锁管理器通过维护锁表控制加锁机制。
死锁的处理
死锁:两个或两个以上事务处于等待状态,每个事务都在等待其中另一个事务释放资源,导致所有事务都无法执行。这种现象称为死锁。
处理死锁方法:
- 引入死锁预防协议,使系统不进入死锁状态:通过对加锁请求进行排序,一事务开始前要锁定所有的数据项。
- 允许系统进入死锁状态,引入死锁检测和死锁恢复机制进行恢复。
死锁的预防:
-
抢占与事务回滚技术:
- 基本措施:每一个事务赋予一个时间戳。若一个事务回滚,则当重启该事务时,必须保持原时间戳。然后采用以下机制:
- * wait-die:如果T1申请的数据被T2持有时,则只有:T1> T2(T2比T1先启动)时, T1等待, 否则回滚
- * wound-wait:与前面条件相同时,只有:T1<T2(T1比T2先启动)时, T1等待,否则回滚
- 基于超时的机制:事先给出事务的等待的时间,超时即回滚。
死锁的检验:等待图
- 等待图中无环则说明没有死锁
- 等待图中有环则说明有死锁
从死锁中恢复:选择事务回滚
- 选择代价最小的事务
- 回滚事务
- 防止饿死,将回滚次数考虑在代价中
- 基于锁的协议开销较大,并发的提升有限度
【北京工业大学-高级数据库系统】