跳至内容
3. MVCC多版本控制

3. MVCC多版本控制

Q: MVCC(多版本控制)原理是什么?

MVCC通过保存数据在某个时间点的快照来实现并发控制,核心组件包括:

1. 隐藏列(2个)

  • 事务ID:记录创建或修改该行数据的事务ID
  • 回滚指针:存储老数据的指针,一旦需要回滚就会通过这个指针来回滚数据

2. 老数据存放位置:undo log

如果事务级别是读已提交就会在undo log中存储数据的版本链

3. 查找机制:快照读(ReadView)

通过ReadView来判断当前事务能看到哪个版本的数据:

  • 读已提交:每次查询都会生成一次ReadView
  • 可重复读:一个事务中只生成一次ReadView

4. ReadView如何定位数据?

ReadView包含三个关键信息:

  • 当前事务ID
  • 未提交事务IDs列表
  • 未开始事务ID

判断逻辑

  1. 与当前事务ID比较:如果相等说明是在当前事务中提交的,可以读取
  2. 与最小事务ID比较:如果小于最小未提交事务ID,说明这个数据是事务开始之前的数据,可以读取
  3. 与最大事务ID比较:如果大于未开始事务ID,说明是在当前事务之后保存的,不可以读取,需要沿着回滚指针找到更老的数据进行比较(重复上述流程)

Q: MVCC在不同隔离级别解决了什么?

读未提交

  • 没有使用MVCC,因为可以读取到没有提交的数据,解决不了幻读

串行化

  • 没有使用MVCC,使用的是表锁

读已提交(解决脏读)

  • 每次执行SELECT的时候都会创建一个新的ReadView
  • 第一次生成ReadView的时候事务C没有提交,所以没有查到C
  • 第二次select的时候又会生成一个ReadView,这时候C已经提交,所以这一次就可以查到(只能读取到别人提交的数据)

可重复读(解决不可重复读)

  • 可重复读是按照事务来生成ReadView的
  • 比如说一个事务里面有两个select,但是只会生成一个ReadView
  • 所以两次select的ReadView是一样的,所以读取到的数据也是一样的
核心理解:MVCC通过版本链和ReadView机制,让不同事务看到不同版本的数据,从而实现无锁的并发读取。