注意: MVCC 只对读需要判断可见性,对写操作直接修改,并维护一个 undo log 链(感觉上像是创建了一个快照)。
工作流程:
1、在当前事务读之前会创建一个 Read View,其中包含几个字段:
m_low_limit_id; /* 大于等于这个 ID 的事务均不可见 */
m_up_limit_id; /* 小于这个 ID 的事务均可见 */
m_ids; /* 创建 Read View 时的活跃事务列表 */
2、对要读取的行,获取其 DB_TRX_ID,即插入或最后一次更新该行的事务 id;
3、若该 DB_TRX_ID < m_up_limit_id,对应记录先于当前事务提交,可见;
4、若该 DB_TRX_ID >= m_low_limit_id,对应记录后于当前事务,不可见;
5、若介于二者之间:
若存在于 m_ids 内,对应记录为当前事务开始时的活跃事务,不可见(通过二分查找是否存在,m_ids递增)
若不存在,对应记录为当前事务开始时的已提交事务,可见
6、若不可见,从该记录行的 DB_ROLL_PTR 所指向的 undo log 链中,取出下一个 DB_TRX_ID,递归地进行步骤3 - 步骤5,直到找到满足的快照版本或返回空。
中间的黄色部分包含 m_ids,以及一部分已提交的事务id。因为需要严格保证小于 m_up_limit_id 的事务均为当前事务创建时已提交的事务,所以 m_up_limit_id 对应的是当前事务创建时 id 最小的活跃事务,但其后可以有一些事务较快地完成了提交。
参考: