【数据库基础】7. 并发控制


基于时间戳的协议


之前已经讲过了调度的概念,SQL 标准规定了四种隔离性级别,在不同的隔离性级别下,我们对调度的要求也不同

但应当注意到,调度一般是由操作系统执行的,数据库系统无法直接控制并行事务的调度方式,因此,数据库系统需要通过一些方法,间接地影响并行事务的调度方式,保证只产生需要的调度,从而实现 SQL 规定的四种隔离性级别

常见的能够间接影响并行事务调度方式的方法有:时间戳、锁、有效性检查、快照隔离等,数据库系统通常用这些方法来实现可串行化的隔离性级别,还有一些其它方法可以用来实现其它隔离性级别

时间戳

基于时间戳的协议,通常会给每个事务分配一个时间戳,时间戳一般是一个整数,不同事务的时间戳一般不同,并且开始时间更晚的事务的时间戳值一般更大

我们有两个很简单的方式给事务分配时间戳:

  1. 一个事务的时间戳等于这个事务开始执行时,系统时钟的值
  2. 维护一个计数器,当一个事务开始执行时,将计数器的值当作这个事务的时间戳,之后将计数器值加一

时间戳排序协议

基本规则

时间戳排序协议的目的是,产生的调度都和一个串行调度冲突等价,并且这个串行调度的串行顺序是事务的时间戳顺序

给每个可能被访问到的数据项维护两个值, W − t i m e W-time Wtime R − t i m e R-time Rtime W − t i m e ( d ) W-time(d) Wtime(d) 维护所有成功执行 w r i t e ( d ) write(d) write(d) 的事务的时间戳最大值, R − t i m e ( d ) R-time(d) Rtime(d) 维护所有成功执行 r e a d ( d ) read(d) read(d) 的事务的时间戳最大值

t i m e ( T ) time(T) time(T) 表示事务 T T T 的时间戳,当事务 T T T 试图执行 r e a d ( d ) read(d) read(d) 时:

  1. t i m e ( T ) < W − t i m e ( d ) time(T)<W-time(d) time(T)<Wtime(d) ,说明 T T T 需要读的值已经被覆盖,因此操作失败,事务 T T T 回滚
  2. t i m e ( T ) ≥ W − t i m e ( d ) time(T) \ge W-time(d) time(T)Wtime(d) ,则可以执行 r e a d ( d ) read(d) read(d) R − t i m e ( d ) R-time(d) Rtime(d) 被设置为 t i m e ( T ) time(T) time(T) R − t i m e ( d ) R-time(d) Rtime(d) 的最大值

当事务 T T T 试图执行 w r i t e ( d ) write(d) write(d) 时:

  1. t i m e ( T ) < R − t i m e ( d ) time(T)<R-time(d) time(T)<Rtime(d) ,则事务 T T T 执行 w r i t e ( d ) write(d) write(d) 会导致其它某些事务 r e a d ( d ) read(d) read(d) 读取的值不正确,因此操作失败,事务 T T T 回滚
  2. t i m e ( T ) < W − t i m e ( d ) time(T)<W-time(d) time(T)<Wtime(d) ,则事务 T T T 试图写入的值已过时,因此操作失败,事务 T T T 回滚
  3. 其它情况下,可以执行 w r i t e ( d ) write(d) write(d) W − t i m e ( d ) W-time(d) Wtime(d) 被设置为 t i m e ( T ) time(T) time(T)

当一个事务因为以上某个原因回滚时,这个事务之后会重启,重启时这个事务将获得一个新的时间戳

根据以上规则和冲突可串行化的定义,可以发现,如果数据库系统采用了时间戳排序协议,就可以保证产生的调度是冲突可串行化的

需要注意的是,仅仅利用以上规则,不能保证产生的调度是可恢复调度,因此时间戳排序协议通常需要一些额外规则,来保证产生的调度是可恢复调度,或者更进一步,是无级联调度,例如,当一个事务 T T T 成功执行了 w r i t e ( d ) write(d) write(d) 后,将 d d d 打上一个未提交标记,当 T T T 提交时,清除该标记,当另一个事务执行 r e a d ( d ) read(d) read(d) 时,若发现 d d d 有未提交标记,则需进行等待,直到未提交标记清除

视图可串行化

对于同一组事务的两个调度 S S S S ′ S' S ,如果满足以下条件:

  1. 如果调度 S S S 中事务 T T T 的一个 r e a d ( d ) read(d) read(d) 操作读取的是 d d d 在调度开始时的初始值,那么调度 S ′ S' S 中事务 T T T 的同一个 r e a d ( d ) read(d) read(d) 操作读取的也是 d d d 的初始值
  2. 如果调度 S S S 中事务 T 1 T_1 T1 的一个 r e a d ( d ) read(d) read(d) 操作读取的是事务 T 2 T_2 T2 的一个 w r i t e ( d ) write(d) write(d) 操作写入的值,那么调度 S ′ S' S 中事务 T 1 T_1 T1 的同一个 r e a d ( d ) read(d) read(d) 操作读取的是 T 2 T_2 T2 的同一个 w r i t e ( d ) write(d) write(d) 操作写入的值
  3. 如果调度 S S S 中最后一个 w r i t e ( d ) write(d) write(d) 操作是由事务 T T T 执行的,那么调度 S ′ S' S 中最后一个 w r i t e ( d ) write(d) write(d) 操作也由事务 T T T 执行

那么我们称调度 S S S 和调度 S ′ S' S 视图等价

如果一个调度 S S S 和某个串行调度视图等价,则我们称 S S S 是视图可串行化的

我们已经知道冲突可串行化的概念了,设冲突可串行化调度的集合为 P 1 P_1 P1 ,视图可串行化调度的集合为 P 2 P_2 P2 ,等价于某个串行调度的调度的集合为 P 3 P_3 P3 ,则 P 1 P_1 P1 P 2 P_2 P2 的子集, P 2 P_2 P2 P 3 P_3 P3 的子集

遗憾的是,对于一个调度是否为视图可串行化调度的判定是一个 NP 完全问题,相比于只需要使用拓扑排序就能判定的冲突可串行化调度,视图可串行化调度的判定速度太慢

Thomas 写规则

可以对时间戳排序协议加以改进,从而提高事务的并发度

当事务 T T T 试图执行 w r i t e ( d ) write(d) write(d) 操作时,若 t i m e ( T ) < W − t i m e ( d ) time(T)<W-time(d) time(T)<Wtime(d) ,原本的做法是将 T T T 回滚,但事实上,若 R − t i m e ( d ) ≤ t i m e ( T ) < W − t i m e ( d ) R-time(d) \le time(T)<W-time(d) Rtime(d)time(T)<Wtime(d) ,那么事务 T T T 执行 w r i t e ( d ) write(d) write(d) 写入的值,根本不会被任何事务读取到

当另一个事务

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值