[CMU 15-445] 19 多版本并发控制协议

1. Overview

前面介绍的各种并发控制协议(如两阶段封锁、乐观并发)都会因为不同事务之间的读写、写读、写写冲突而造成阻塞,影响事务的并发性能。多版本并发控制协议执行写操作时会创建一个新版本,数据库中存在多个不同版本的历史数据,事务执行读操作时只会根据其时间戳读取一个应该看到的历史版本。MVCC由于读写不会发生冲突,因此并发性能效果会更好,缺点在于众多的历史版本会占据较多的存储空间。

存储历史版本并非一无用处,MVCC使用历史版本可以支持历史数据查询。

下面是一个MVCC的例子,假设当前设置的事务并发隔离级别是串行化。首先,T1和T2都被分配了时间戳,分别是1和2。状态A的初始版本为A0,值为123,T1检查A0的时间戳小于它的时间戳且为最新值,读取A0的值。

T2写入一个A的新值A1,且Begin的时间戳为2,将A0的End处时间戳标为2。

T1读取A,由于前面提到隔离级别是串行化且T1的时间戳为1,因此这时候T1读取的依旧是A0。

下面是另一个MVCC并发控制例子,首先T1写A,创建新版本A1,将A0的End标记为1。

T2读取A,由于隔离级别设置为串行化且T1还没有被提交,因此T2读到的A状态依旧为A0。

随后T2准备写A,由于隔离级别设置为串行化但是A现在已经被T1写入且End还未标记,所以阻塞(感觉这边可以不阻塞,后面读的时候根据Begin和End以及自己的时间戳判断该读哪个就行了)。

T1继续读A,这时应该读A1,因为T1在前面写了A1。

T1在COMMIT了之后,T2可以继续执行。

2. MVCC Control Design

MVCC 不同于之前提到的并发控制协议,它本质上通过多版本实现了基于快照隔离(Snapshot Isolation,SI)的事务并发机制。

多版本数据的存储也是MVCC中需要解决的问题,同时能够方便事务检查出当前对其可见的历史状态。

主要存储方式有三种(非常常见的存储策略)。其中,Append-Only每次将新版本数据直接追加到相同的存储表中;Time-Travel将老版本单独存储到一张表中;Delta Storge只将本次事务修改的值存放到单独的一张表中。

Append-Only 每次将新版本数据追加到Main Table中,Main Table保存所有的历史状态数据。

而 version chain 中值的排列顺序可以按照从旧到新或者从新到旧的顺序排列。

Time Travel 每次将旧的版本放在Time Travel表中,Main Table存放新的值。

Delta Storage 每次仅将变化的部分存入单独的 Delta Storage 表中。

对于版本过旧,不会再有交易访问的数据,DBMS将会对其删除释放空间。

垃圾回收有两种粒度,一个是Tuple级,一个是Transaction级。

DBMS单独启动一个线程扫描数据库,决定各个版本是否需要清除。

或者不需要DBMS单独启动一个线程负责清理数据,把这个事情放在每次数据库操作中,当访问多版本数据时顺带将数据更新(一种协同操作的概念,本质还是一种pipline)。

事务级别垃圾回收,每当一个事务结束时候DBMS判断其是否对于其他事务可见。

不同事务为了快速找到version chain,利用索引来加速,索引可以直接存物理地址或者设置一个中间层,这样可以减少多个索引更新的开销。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值