MVCC简介
- Innodb高并发的原因:所有普通select均为快照读,快照读使用 MVCC ,不加锁。
- MVCC实现mysql中的RC,RR隔离级别,其余两个隔离级别和MVCC无关。
MVCC实现
数据多版本
- 数据历史版本存在undo日志中:
- 通过事务id标识是哪个事务的操作。
- 通过回滚指针串联历史版本数据。
- 插入时:回滚指针为null。
- 更新时:排他锁锁定行,修改前的值copy到undo中,修改当前值并使回滚指针指向Undo中的备份。
- 多次更新时:比如一个值从1改成2->3->4,回滚段串成到最老版本的链表,快照读时从当前值4开始寻找可见版本。
- 系统里没有比这个回滚段更早的read-view时:回滚段被删除。
可见性
- 查询逻辑:普通select为快照读,一个数据版本,对于一个事务来说的可见性如下
- 可见:自己更新的版本、在视图创建前提交的版本。
- 不可见:其他事务未提交的版本、在视图创建后提交的版本。
- 更新逻辑:更新数据是先当前读,后写。当前读需要加锁:包括update,select + for update,select + lock in share mode
可见性实现
- 核心思路:一致性视图和当前事务id比较。
- 一致性视图:视图数组+高水位。每个事务维护一个视图数组,保存创建视图时活跃事务id。
- 低水位(最小未提交事务):视图数组中事务id最小值。
- 高水位(最小未开始事务):系统已经创建过的事务最大值+1。
- 视图数组创建时机:
- RR级别:第一个查询语句开始时,当前所有活跃事务(启动还未提交)。
- RC级别:每个查询语句开始时,当前所有活跃事务。
- 数据版本事务id的状态和可见性:
- [0,低水位):已提交事务,可见。
- [低水位,高水位):数据版本的事务id在视图数组中,未提交,不可见;否则可见。
- [高水位,+∞):将来启动的事务,不可见。
隔离级别和视图
- RC。每一条语句执行前重新计算一致性视图。
- RR。事务开始时创建一致性视图。