锁
简单锁
- 共享锁S:如果事务Ti获得了数据项Q上的共享锁S,则Ti可读但不能写Q
- 排他锁X:如果事务Ti获得了数据项Q上的排他锁X,则Ti可读又可写Q
事务根据自己对数据项 Q 进行的操作类型申请适当的锁
事务只有在并发控制管理器授予所需的锁之后才能继续其操作
简单锁相容矩阵
申请
- lock-S(
Q ):申请共享锁 - lock-X( Q ):申请排他锁
释放
- unlock(Q):释放锁
授权在#Q#上加#M#型锁的条件
- 不存在在数据项#Q#上持有与#M#型锁冲突的锁的其他事务
- 不存在等待对数据项#Q#加锁且先于事务申请加锁的事务
两阶段封锁协议
- 增长阶段:事务可以申请共享锁、排他锁,能将共享锁升级为排他锁,不能释放锁
- 缩减阶段:事务可以释放共享锁、排他锁,能将排他锁降级为共享锁,不能获得新锁
最初事务处在增长阶段,事务根据需要获得锁,获得最后加锁的位置称为事务的封锁点。一旦事务释放了锁,就进入缩减阶段
可以保证冲突可串行化
级联回滚可能发生
严格两阶段封锁协议
除了要求两阶段封锁协议,还要求事务持有的所有排他锁必须在事务提交之后方可释放
可以保证冲突可串行化
级联回滚可以避免
强两阶段封锁协议
除了要求两阶段封锁协议,还要求事务持有的所有锁必须在事务提交之后方可释放
可以保证冲突可串行化
级联回滚可以避免
多粒度
允许各种大小数据项并定义数据粒度的层次结构,其中小粒度数据项嵌套在大粒度数据项中实现
- 共享锁S:如果事务Ti获得了数据项Q上的共享锁S,则Ti可读但不能写Q
- 排他锁X:如果事务Ti获得了数据项Q上的排他锁X,则Ti可读又可写Q
- 共享型意向锁IS:在树的较低层进行显式封锁,但只能加共享锁
- 排他型意向锁IX:在树的较低层进行显式封锁,可以加共享锁和排他锁
- 共享排他型意向锁SIX:以该结点为根的子树显式加共享锁,树的较低层显式加排他锁
多粒度锁相容矩阵
多粒度加锁释放顺序
- 多粒度协议要求加锁是自顶向下的顺序(根到叶)
- 锁的释放是自底向上的顺序(叶到根)
多粒度封锁协议
事务按照如下规则对数据项
- 事务必须遵从锁相容函数
- 事务必须先封锁树的根结点,并且可以加任意类型的锁
- 仅当当前对
Q
的父结点具有IX或IS锁,事务对结点
- 仅当当前对
Q
的父结点具有IX或SIX锁,事务对结点
- 仅当事务未曾对任何结点解锁时,事务可对结点加锁
- 仅当事务当前不持有
Q
的子结点的锁时,事务可对结点
死锁
如果存在一个事务集 {T0,T1,…,Tn} ,使得 T0 在等待被 T1 锁住的数据项, T1 在等待被 T2 锁住的数据项…, Tn−1 在等待被 Tn 锁住的数据项, Tn 在等待被 T0 锁住的数据项,那么系统处于死锁状态
预防
- 通过对加锁请求进行排序或要求同时获得所有的锁来保证不会发生循环等待
- 每当等待可能导致死锁时,进行事务回滚而不是等待加锁
检测
- 等待图:
G=(V,E)
,
V
是顶点集,由所有事务组成,
E 是边集,边集每一个元素是一个有序对 Ti→Tj ,如果 Ti→Tj 属于 E ,则表示事务Ti 在等待 Tj 释放所需要的数据项。当且仅当等待图包含环时,系统存在死锁
恢复
- 回滚一个或多个事务
- 选择牺牲者
- 选择最小代价的事务
- 回滚
- 彻底回滚
- 部分回滚
- 饿死
- 保证一个事务被选为牺牲者的次数有限