原理

基于 (隐藏字段 + undolog + readView)来实现MVCC

  • undolog

    修改数据时,将该记录写入到版本链中,undolog, 每次放在头部。

  • 行隐藏字段:

    db_trx_id:事务ID,全局唯一

    roll_pointer 版本链指针

mvcc

ReadView中的统计值:

  • m_ids 当前活跃的事务集合(所有未提交的事务)
  • min_trx_id m_ids中最小的。即最小的活跃事务ID
  • max_trx_id 版本链头的事务+1。max_trx_id并不是m_ids中的最大值,事务ID是递增分配的。比方说现在有id为1,2,3这三个事务,之后id为3的事务提交了。那么一个新的读事务在生成ReadView时,m_ids就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4
  • creator_trx_id 当前创建这个视图的事务ID

根据上图,当前事务ID为201时,统计值如下:

  • m_ids = [90,100, 200]

  • min_tx_id = 90

  • max_tx_id = 200 + 1 = 201

  • creator_trx_id = 201

判断规则

undolog链表头部开始遍历

伪代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if (该记录trx_id == 当前自己的事务id) {
那么就是当前事务自己修改的,当然可以访问 true
} else {
if(该记录trx_id < min_tx_id) {
那么该记录的事务在自己生成readView前就已经提交了,可以被当前事务访问 true
} else {
if(该记录trx_id >= max_tx_id) {
那么该事务是在readview生成之后才开启,不能被当前事务访问 false
} else {
if(min_tx_id < 该记录trx_id < max_tx_id) {
if(该记录trx_id 在 m_ids中){
说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被访问 false
} else {
说明创建ReadView时生成该版本的事务已经被提交,可以被当前事务访问 true
}
}
}
}
}