ch18
1. 证明两阶段锁协议(Two-Phase Locking Protocol)能够保证冲突可串行化,且事务可以根据它们的锁点进行串行化。
两阶段锁协议指某事务会经历增长阶段与缩减阶段。考虑两个事务T1,T2对数据项A进行操作,若T1对A的操作处于T2的增长阶段与缩减阶段中间。则T1获得A数据项的锁后,T2又获得A数据项的锁,则两个锁均为读锁:lock-S(A),则明显T1对A的操作可以换到T2之前,也可以换到T2之后;否则不妨假设T1对数据项A的锁为写锁:lock-X(A),则T1对A的操作不可能处于T2的增长阶段与缩减阶段中间,所以,两个事务对A的操作可分离。综上,事务可以根据锁点冲突可串行化。
2. 假设数据库的锁层次包括数据库、关系和元组。
a. 如果一个事务需要从关系 r 中读取大量元组,它应该获取哪些锁?
b. 现在假设事务在读取了大量元组后想要更新 r 中的一些元组。它应该获取哪些锁?
c. 如果在运行时事务发现需要实际更新大量元组(在获取锁时假设只有少量元组会被更新),这将对锁表造成什么问题?数据库可以采取什么措施来避免这个问题?
a. 应该获取对关系的读锁:lock-S(r),以及关系的所有后裔即关系内所有元组的读锁(实际不产生)。
b. 应获取关系中对应元组的写锁:lock-X(A)
c. 这会导致锁表中保存大量的写锁,可以改用对关系的写锁:lock-X(r)
3. 考虑一个以根树(rooted tree)形式组织的数据库。假设在每对顶点之间插入一个虚拟顶点。说明,如果在新树上遵循树协议(Tree Protocol),我们将获得比在原始树上遵循树协议更好的并发性。
在原始树中,每个节点的子节点是串行的,因为按照树协议的要求,必须按顺序访问它们。但在新树中,通过在每对顶点之间插入虚拟顶点,我们增加了树的层数,每对顶点之间的虚拟顶点形成了新的并行路径。这意味着在新树上可以并行执行的事务数量更多,从而提高了并发性能。
4. 在多粒度锁定中,隐式锁定和显式锁定有什么区别?
显示锁:指事务对某个数据库或关系或元组直接加的锁。
隐式锁:指事务对某个对象显示锁后,会对对象的后裔加隐式锁,比如若对关系加显示锁,则会对关系下的所有元组加隐式锁,若对数据库加显示锁,则会对数据库中所有关系,对所有关系的所有元组加隐式锁。
5. 考虑以下两个事务:
T34:
read(A);
read(B);
if A = 0 then B := B + 1;
write(B).
T35:
read(B);
read(A);
if B = 0 then A := A + 1;
write(A).
为两个事务添加锁定(lock)和解锁(unlock)的指令,使事务 T34 和 T35 遵循两阶段锁协议(Two-Phase Locking Protocol)。说明这样会不会导致死锁。
T34 | T35 |
lock-S(A) | |
lock-S(B) | |
lock-S(B) | |
lock-S(A) | |
lock-X(A) | |
lock-X(B) | |
unlock-X(B) | |
unlock-S(B) | |
unlock-S(A) | |
unlock-X(A) | |
unlock-S(A) | |
unlock-S(B) |
在第5行发生死锁,T34握着对数据项A的读锁,导致T35不能获得对数据项A的写锁,同时T35握着对数据项B的读锁,导致T34不能获得对数据项B的写锁。故会导致死锁。