1.简介
多版本并发控制主要是存储引擎面对并发读写提高并发能力的手段之一,主要实现方式是数据存在多个版本,每个读写操作会分配一个版本号用于确定可见的数据版本范围,最终实现读不加锁,只有写操作需要加锁,降低锁竞争。
2.常见读实现
2.1 MySql的Innodb
原理
Innodb维护了当前已启动但是未提交的事务集合,每个事务开启时候,会分配一个全局事务ID,创建一个可见的事务版本范围。低水位就是事务集合中最小的事务ID,高水位就是事务集合中最大事务ID + 1.当前事务的可见性规则如下(哪些版本的数据可见,并选择可见版本中的最大版本):
- 数据版本 < 低水位,可见
- 数据版本 > 高水位,不可见
- 数据版本在黄色区域中,如果版本在开启事务的时候已提交,则可见;否则不可见 对于不可见的数据,需要使用undolog计算得到可见的数据版本,低水位以及更低的版本事务创建的undolog会被清理。 Innodb的版本是行粒度的。
缺点
- 长事务会导致回滚段太长,使得undolog计算耗时增加
- 需要删除无用的回滚段
2.2 HBase
原理
HBase读操作会分配一个读取点(当前已完成的写操作中的写序号最大整数,序列号是Region粒度上实现的单调递增),HBase的版本粒度是Cell粒度的。
缺点
由于HBase每次变更都是一条新的写入而不是原来数据的修改,因此会占用磁盘更大的空间。
2.3 MongoDB的WiredTiger
原理
和Innodb的实现类似,也是使用全局事务ID。开启事务时创建可见事务范围,可见性规则同Innodb.当数据版本大于可见版本时,不是使用undolog计算可见数据而是,遍历列表实现的。历史版本的值用列表维护。
缺点
- 多版本的存储
- 无用版本的删除