两阶段封锁协议
- 保证可串行性的协议:
增长阶段:只能获得锁
缩减阶段:只能释放锁
基于时间戳的协议
每个事务T都有一个时间戳(事务开始时间),记作TS(Ti)
记W-timestamp(Q)为成功执行write(Q)的所有事务的最大时间戳
记R-timestamp(Q)为成功执行read(Q)的所有事务的最大时间戳
- 假设Ti发出read(Q):
若TS(Ti)<W-timestamp(Q),则回滚Ti
否则执行read操作
- 假设Ti发出write(Q):
若W-timestamp(Q)<R-timestamp(Q),则回滚Ti
若W-timestamp(Q)<W-timestamp(Q),则回滚Ti
否则执行write操作
基于有效性检查的协议
- Ti分三个阶段:
1.读阶段:所有数组读入局部变量中,写操作保存在局部变量中
2.有效性检查阶段
3.写阶段
Start(Ti):事务开始时间
Validation(Ti):事务开始有效性检查阶段
规定TS(Ti) = Validation(Ti):在冲突频率低的情况下期望有更快的相应时间
- 有效性检查:
所有满足TS(Tk) < TS(Ti)的事务Tk必须满足下面两个条件之一:
1.Finish(Tk) < Start(Ti)
2.Tk所写的数据项与Ti所读的数据项不相交。
多版本机制
每个数据项Q有一个版本序列
- 每个版本序列包括:
版本值
W-timestamp(Q):创建该版本的事务时间戳
R-timestamp(Q):所有成功读取该版本的最大时间戳
- 多版本时间戳排序机制:
当Ti发出读或写请求,令Qk为表示Q的写时间戳<=TS(Ti)的最大写时间戳
1.若Ti发出读请求,则返回Qk内容
2.若Ti发出写请求,且TS(Ti)<R-timestamp(Qk),则回滚
TS(Ti)=R-timestamp(Qk),则覆盖
TS(Ti)>R-timestamp(Qk),则创建新版本
快照隔离
事务开始执行时给它数据库的一份快照,在快照上进行操作
先提交者获胜:当T进入部分提交状态,检查是否有与T并发执行的事务,对T打算写入的某些数据已经更新写入数据库,如果有则终止T
先更新者获胜:当T试图更新一个数据项,请求该数据项的一个写锁,如果获得了锁,检查这个数据是否被任何并发事务更新,如果有则终止
快照隔离不保证可串行化
SQL Server提供可串行化隔离级别+快照隔离级别
Oracle 和 PostgreSQL提供的可串行化隔离级别为快照隔离
索引结构中的并发
- 蟹行结构:
当查找码时,首先用共享模式锁住父节点,移动到子节点时,在子节点获得共享锁,释放父节点共享锁
插入删除时:
用排他锁锁住叶节点
如果需要分裂或合并,用排他锁锁住父节点,释放子节点和兄弟节点的锁
B-link树:每个节点维护一个指针指向右兄弟节点