锁的类型
锁相容性矩阵 Lock-Compatibility Matrix
S | X | |
---|---|---|
S | True | False |
X | False | False |
锁的缺陷
示例:设计不佳导致无效的锁
- 上述锁无法保证序列执行:若在上述代码的 A 与 B 读取之间,其它事务对 A 或 B 的值进行了修改,则上述代码显示的(A+B)将与实际不符
示例:死锁 Deadlock
- $T_4$ 的
lock-s(B)
等待 $T_3$ 释放 B 的排他锁, $T_3$ 的lock-x(A)
等待 $T_4$ 释放 A 的共享锁,导致两个事务互相等待,造成死锁- 为解决死锁, $T_3,T_4$ 其一必须进行回滚并释放锁
两阶段锁 2PL
对于每一个事务,分为两个阶段:
阶段 1:Growing Phase
在该阶段中,事务可以获得锁,但不可以释放锁
阶段 2:Shrinking Phase
在该阶段中,事务可以释放锁,但不可以获得锁
两阶段锁的分析
对某个调度的全部事务使用两阶段锁,可保证调度是冲突可序列化的
证明:
不是所有冲突可序列化的调度都可以使用两阶段锁
对某个调度的部分事务使用两阶段锁、部分事务不使用两阶段锁,则该调度不一定是冲突可序列化的;因此,为保证冲突可序列化,应当对调度的全部事务都使用两阶段锁
两阶段锁无法消除出现死锁的可能性
变体:Strict 2PL
变体:Rigorous 2PL
变体:2PL With Lock Conversions
对于每一个事务,分为两个阶段:
阶段 1:Growing Phase
在该阶段中,事务可以获得锁,可以将 S 锁转化为 X 锁(Upgrade),但不可以释放锁
阶段 2:Shrinking Phase
在该阶段中,事务可以释放锁,可以将 X 锁转化为 S 锁(Downgrade),但不可以获得锁
示例:
读与写的自动上锁
// Read D
if (T_i has a lock on D) {
read(D);
}
else {
wait until no other transaction has a lock-X on D...
lock-S(D);
read(D);
}
// Write D
if (T_i has a lock on D) {
write(D);
}
else {
wait until no other transaction has a lock on D...
lock-X(D);
write(D);
}
// All locks are released after commit or abort
锁管理器 Lock Manager
示例:锁表的实现
- 数据项 123 被事务 T1 和 T8 的共享锁锁定,事务 T2 等待该数据项的排他锁
基于图的锁
树协议 Tree-Protocol
示例: