一、基于锁的协议
1. 锁
本节中考虑两种:
- 共享锁(shared lock):若事务T获得了数据项Q上的共享锁(记为S),则它可读但不可写Q。
- 排他锁(exclusive lock):若事务T获得了数据项Q上的排他锁(记为X),则既可读也可写Q。
每个事务应当针对子集对数据项Q进行的操作类型申请锁,并由不乏控制管理器授予所需锁后才能操作。
锁相容关系:
要访问一个书记想,事务必须首先给数据项加锁,如果其一百倍零一十五加上了不相容的锁,则在所有其他事务持有的不相容类型的锁被释放之前,并发控制管理器不会授予锁。因此该事务将等待,直至其他食物持有的不相容类型锁被释放。
2. 死锁与饿死
这样的情况下,锁不会自然取消,需要对T3或T4进行回滚。应当注意到,思索事实上体现了并发控制中的访问冲突,因此它一定程度上是必然会出现的。
饿死(starvation)是指希望对某数据项上X锁的事务因对该数据项上S锁的事务不断插队而不断回滚的情况。使用以下条件能够防止饿死:加锁的条件应该是:
- 不存在数据项Q上持有与M型锁冲突事的锁的其他事务
- 不存在一个等待对数据项Q枷锁且现由于Ti申请加锁的事务
3. 两阶段封锁协议(2PL protocol)
其要求每个事务(注意2PL的单位)分两个阶段:
- 增长阶段:事务仅获得锁,不释放锁
- 缩减阶段:事务仅释放锁,不获得锁
封锁点(lock point):在调度中,该事务获得其最后枷锁的位置
多事务可以根据其封锁点进行排序,而这个顺序就是事务的一个可串化顺序
- 严格(strict)两阶段封锁协议:用于防止级联回滚
要求事务持有的排他锁必须在事务提交之后方可释放 - 强(rigorous)两阶段封锁协议:
要求事务提交之前不得释放恩和锁
锁转换
- 可以在增长阶段进行锁升级,将共享锁升级为排他锁
- 可以在缩减阶段进行锁降级,将排他锁转换为共享锁
锁转换一定程度上防止死锁的发生
4. 锁管理器
上图就是所管理器中锁表的数据结构,其中每个数据项被映射到以溢出链为实现方式的哈希表中,数据项指向在它身上加的(将要加的)一系列锁。
- 黑色举行代表已加的锁,白色矩形则代表仍等待的request
- 锁表会记录锁的类型
- 新的request被添加在数据项指向链表的末尾,并在与之前的锁兼容时被授权(变黑)
- 解锁操作在数据项上对应地删除举行
- 如果事务被终止,所有正在等待的request都会被删除
5. 基于图的协议
基于图协议看重的是访问数据项的顺序,因而对所有数据项集合
D
=
{
d
1
,
d
2
,
.
.
.
,
d
n
}
D=\{d_1,d_2,...,d_n\}
D={d1,d2,...,dn},满足偏序
→
\rightarrow
→:
如
果
d
i
→
d
j
,
则
任
何
访
问
两
者
的
事
务
必
须
首
先
访
问
d
i
,
再
访
问
d
j
如果d_i\rightarrow d_j,则任何访问两者的事务必须首先访问d_i,再访问d_j
如果di→dj,则任何访问两者的事务必须首先访问di,再访问dj
这样的偏序关系构成的有向无环图成为数据库图(database graph),应当注意的是,简单树形协议只使用排他锁。
树形协议的加锁规则
- Ti首次加锁可以对任何数据项进行
- 此后Ti对数据项Q加锁的前提是Ti当前持有Q的父项上的锁
- 对数据项的解锁可以所示进行
- 数据项被某个事务加锁并解锁后,该事务不能再为该数据项加锁
例子:
基于图的加锁协议不保证可恢复性和无级联回滚
二、多粒度与意向锁
某些情况下需要把多个数据项聚为一组,将它们作为一个同步单元,因此系统应当定义多粒度的机制,允许数据项以不同大小被同步操作。多粒度树中的非叶节点表示与后代相关联的数据。
在上图中,从上到下的层级分别问数据库,类型空间,数据表(文件)和元组。
树中的每个结点都可以单独枷锁,可以使用共享锁与排他锁。然而当事务对一个结点加任何一种锁时,该事务也以同样类型的锁隐式地封锁这个节点的全部后代节点。
例如:事务Ti给Fb显式加排他锁,则其也给属于它的所有文件记录隐式加了排他锁。但当事务Tj希望封锁Fb下的记录
r
b
k
r_{b_k}
rbk时,它并没有被显式而只是被隐式加锁。所以系统判断Tj是否可以封锁
r
b
k
r_{b_k}
rbk的方法就是它Tj必须从树根到
r
b
k
r_{b_k}
rbk遍历,如果发现路径上某个结点的锁与要加的锁类型不相容,则它必须延迟。
再假设Tk希望封锁整个数据库,理论上说它只需给层次结构图的根节点加锁。但它的加锁不会成功,因为目前Ti再树的某部分持有锁,对这种情况进行甄别的方法1时引入**意向锁(intention lock)**类型。
关键:在一个结点显示加锁之前,该节点的全部祖先均加上意向锁,因此,事务不必搜索整棵树就能判定是否能给一个结点加锁。
多出的类型:
- 共享型意向锁(IS):将在树的较低层进行显示封锁,但只能是共享锁
- 排他性意向锁(IX):将在树的较低层进行显示封锁,可以是共享或排他锁
- 共享排他型意向锁(SIX):以该节点为根的子树显式加了共享锁,并将在树的更底层显式加排他锁
相容情况如下:
多粒度封锁协议的规则
- 事务必须遵从上图索时的锁类型相容函数
- 事务Ti必须首先封锁书的根节点,并且可以加任意类型的锁
- 对某个结点加S/X锁,则意味着其后代都至少加了S/X锁
- 仅当Ti当前对Q的父节点有IS或IX锁时,Ti对结点Q可以加S和IS锁
- 仅当Ti当前对Q的父节点有IX或SIX锁时,Ti对结点Q可加X,SIX和IX锁
- 仅当Ti未曾对任何节点解锁时,Ti可对节点枷锁(也即Ti是2PL的)
- 仅当Ti不持有Q的子节点的锁是,Ti可对结点Q解锁
- 加锁按照自顶向下的顺序,解锁按照自底向上的顺序
三、死锁处理
1. 死锁预防
- 方法一:通过对meidangd加锁请求进行排序或要求同时获得所有的锁来保证不会发生循环等待。
- 方法二:每当等待有可能导致死锁时,进行事务回滚而不是等待加锁