6. MVCC底层原理剖析
6.1 基本概念
当前读
读取的是记录的最新版本。读取时还要保证其他的并发事务不能修改当前记录。会对读取的记录进行加锁。对于我们日常的操作,比如:
select ... lock in share mode; # 共享锁 - 当前读
select ... for update,delete,insert; # 排他锁 - 当前读
以上都是当前读。
快照读
对当前的数据生成一个快照, 后续的数据基于当前数据进行增删改查。
简单的select语句(不加锁)就是快照读。非阻塞读。
Read Committed: 每次select,都生成一个快照读
Repeatable Read:开启事务后,第一个select语句才是快照读的地方
Serializable: 快照读会升级为当前读
MVCC
全称Multi-Version Concurrency Control:多版本并发控制
指维护数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读的功能。
MVCC具体的实现,还需要依赖于数据库记录的二/三个隐式字段, undo log日志, readview
6.2 三个隐式字段
| id | name | age | DB_TRX_ID | DB_ROLL_PTR | DB_ROW_ID |
|---|---|---|---|---|---|
| 1 | tom | 19 | 当前事务ID | 回滚指针 | 隐式主键 |
-
DB_TRX_ID
最近修改事务ID,记录更新这条数据记录的事务ID
-
DB_ROLL_PTR
回滚指针,指向这条数据的上一个版本,用于配合undo log
-
DB_ROW_ID
隐藏主键,没有指定主键,会生成该字段
6.3 undo log
回滚日志, 在insert, update, delete的时候产生的。 便于回滚数据。
对于insert操作, 产生的undo log只在回滚时需要,事务提交后,可被立即删除。
对于update和delete操作,产生的undo log不仅在回滚时需要,快照读时也需要,事务提交后不会立即删除。
6.4 Read View
Read View 是快照读SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的事务)id。
Read View包含4个核心字段
- m_ids: 当前活跃事务的id集合
- min_trx_id:最小活跃事务id
- max_trx_id:当前最大活跃事务id + 1
- create_trx_id: Read View创建者的事务ID
不同隔离级别, Read View生成的规则不同。
-
READ UNCOMMITTED: 不生成
-
READ COMMITTED: 在事务中每执行一次快照读时生成Read View
-
REPEATABLE READ: 在事务中第一次执行快照读时生成Read View, 后续复用该Read View。
-
SERIALIZABLE:不生成
undo log版本链数据访问规则:
- trx_id == create_trx_id : 可以访问该版本数据. 该条件成立说明就是当前事务更改的该数据。
- trx_id < min_trx_id : 可以访问该版本数据。该条件成立,说明更改这条数据的事务已经提交。
- trx_id >= max_trx_id: 不可以访问。 该条件成立, 说明这条数据是现在的Read view生成后的新开事务更改的。
- min_trx_id <= trx_id < max_trx_id: 只有在trx_id不再m_ids的集合中时,这条数据才可以被访问。因为说明这个trx_id的事务已经提交。

浙公网安备 33010602011771号