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
判断逻辑:
- 与当前事务ID比较:如果相等说明是在当前事务中提交的,可以读取
- 与最小事务ID比较:如果小于最小未提交事务ID,说明这个数据是事务开始之前的数据,可以读取
- 与最大事务ID比较:如果大于未开始事务ID,说明是在当前事务之后保存的,不可以读取,需要沿着回滚指针找到更老的数据进行比较(重复上述流程)
Q: MVCC在不同隔离级别解决了什么?
读未提交
- 没有使用MVCC,因为可以读取到没有提交的数据,解决不了幻读
串行化
- 没有使用MVCC,使用的是表锁
读已提交(解决脏读)
- 每次执行SELECT的时候都会创建一个新的ReadView
- 第一次生成ReadView的时候事务C没有提交,所以没有查到C
- 第二次select的时候又会生成一个ReadView,这时候C已经提交,所以这一次就可以查到(只能读取到别人提交的数据)
可重复读(解决不可重复读)
- 可重复读是按照事务来生成ReadView的
- 比如说一个事务里面有两个select,但是只会生成一个ReadView
- 所以两次select的ReadView是一样的,所以读取到的数据也是一样的
核心理解:MVCC通过版本链和ReadView机制,让不同事务看到不同版本的数据,从而实现无锁的并发读取。