MVCC实现原理
MVCC的基本概念
MVCC,一个数据的多个版本,使得读写操作没有冲突。
在多个事务并发的情况下,确定到底要访问哪个版本。
MVCC实现原理
MVCC实现依赖于隐式字段,undo log日志,readView
隐式字段
在mysql用户自定义的字段后面,隐藏了MySQL提供好的3个隐藏字段
DB_TRX_ID
:最近修改事务IDDB_ROLL_PTR
:指向回滚段中的undo log记录,指向上一个版本DB_ROW_ID
:隐藏主键(当表无主键时自动生成)
undo log日志
回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。
当insert的时候,产生的undolog日志只在回滚时需要,在事务提交后,可被立即删除。
而update、delete的时候,产生的undolog日志不仅在回滚时需要,mvcc版本访问也需要,不会立即被删除。
undo log版本链
undo log日志 记录 数据修改前的值,形成版本链(相当于一个修改记录)
ReadView机制 事务执行时会生成ReadView
ReadView(读视图)是 快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。
- 当前读:读取的是最新版本,会加锁,读取时不会被修改。
- 快照读:不加锁,读取的是记录数据的可见版本,可能是历史数据。
ReadView包含4个核心字段
m_ids
:当前活跃事务ID集合,还未提交的 事务的集合。min_trx_id
:最小活跃事务IDmax_trx_id
:预分配的下个事务ID,当前最大事务id+1(事务id是自增的)creator_trx_id
:创建该ReadView的事务ID
版本链 数据访问规则
DB_TRX_ID:最近修改的事务id
-
如果
DB_TRX_ID
小于min_trx_id
,说明该版本在ReadView创建前已提交,可访问 -
如果
DB_TRX_ID
大于等于max_trx_id
,说明该版本在ReadView创建后生成,不可访问 -
如果
DB_TRX_ID
等于creator_trx_id
,说明该版本由当前事务修改,可访问 -
如果
DB_TRX_ID
在m_ids
列表中,说明该版本由未提交事务创建,不可访问
不同隔离级别,生成的ReadView的时机不一样
- READ COMMITTED(RC):每次查询都生成新的ReadView,能看到其他事务已提交的修改。(每次查询时我都来判断:最新提交的事务是谁,我就读谁)
- REPEATABLE READ(RR):仅在第一次查询时生成ReadView并复用,保证事务期间看到的数据版本一致。(第一查询,中间改动了,我还是复用第一次的查询,不能识别到中间改动了)