跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何理解MVCC的多版本并发控制_Undo Log版本链与Read View

Undo Log版本链通过DB_ROLL_PTR指针将同一行的多个历史版本串联成单向链表,头部为最新已提交版本,遍历时依可见性规则回溯查找。 Undo Log版本链是怎么串起来的 每一行数据在InnoDB里都有两个隐藏字段:
DB_TRX_ID
(最近修改它的事务ID)和
DB_ROLL_PTR
(指向旧版本的指针)。每次
UPDATE
或
DELETE
,InnoDB不会直接覆盖原数据,而是把旧值写进Undo Log,并用
DB_ROLL_PTR
把它连到上一个版本,形成一条从新到旧的单向链表。 注意:只有
INSERT
产生的Undo Log在事务提交后可立刻清理,因为没“上一版本”;而
UPDATE/DELETE
的Undo Log必须保留到所有可能用到它的Read View都失效之后——否则快照读会找不到历史版本。 版本链头部永远是最新已提交版本(不是“当前未提交”的那个),遍历时从
DB_ROLL_PTR
出发,逐级回溯 如果某次查询需要读取“事务开始时”的快照,但链上最新版的
DB_TRX_ID
不可见,就得顺着指针往下找,直到找到第一个满足可见性规则的版本 版本链不跨行、不跨表,只针对同一行记录;不同事务对同一行反复更新,链就变长,但不会无限增长——Purge线程会在后台异步清理无用版本 Read View生成时机和判断逻辑 在
REPEATABLE READ
隔离级别下,Read View只在事务中**第一次执行快照读(即普通
SELECT
)时生成**;而在
READ COMMITTED
下,每次
SELECT
都会新建一个Read View。它不是“静态快照”,而是一套动态可见性规则。 Read View包含四个关键信息:
m_ids
(当前活跃事务ID集合)、
min_trx_id
(
m_ids
中最小ID)、
max_trx_id
(下一个待分配事务ID,非最大活跃ID)、以及创建该View的事务自身ID。 判断某行是否可见:先看它的
DB_TRX_ID
—— 若小于
min_trx_id
,说明修改它的事务早已提交,可见 若
DB_TRX_ID
在
m_ids
里,说明那事务还没提交,不可见 若
DB_TRX_ID
≥
max_trx_id
,说明该版本由“未来事务”写入(ID分配是严格递增的),也不可见 其他情况(比如等于当前事务ID),则可见 —— 这就是为什么你能在自己事务里读到自己刚改的数据 为什么“可重复读”能避免不可重复读,却不一定防幻读 不可重复读的本质是:同一行数据被其他事务反复
UPDATE/DELETE
并提交,导致你两次
SELECT
看到不同值。MVCC靠固定Read View解决了这个问题——后续查询都复用第一次生成的
m_ids
和水位线,旧版本只要还在链上,就能读出来。 但幻读是另一回事:它源于其他事务
INSERT
了新行,而这些新行的
DB_TRX_ID
可能落在你的Read View可见范围内(比如比
min_trx_id
还小),于是第二次
SELECT
突然多出几条记录。 MySQL的
REPEATABLE READ
通过间隙锁(Gap Lock)+ Next-Key Lock 来堵住插入,不是靠MVCC本身 如果你关掉
innodb_locks_unsafe_for_binlog
或用了
READ COMMITTED
,间隙锁会退化,幻读就容易出现 单纯依赖MVCC无法拦截
INSERT
带来的新行,因为新行没有“旧版本链”,它的
DB_TRX_ID
就是当前事务ID,天然满足可见条件 常见误判:为什么我查不到刚提交的数据 最常遇到的不是“读到旧数据”,而是“明明提交了,怎么还查不到”。典型场景是:事务A执行
UPDATE
并
COMMIT
,事务B却在之后的
SELECT
中看不到变更。 这往往不是MVCC的问题,而是事务B的隔离级别或启动时机不对: 事务B在事务A提交前就已启动,并且是
REPEATABLE READ
,那它的Read View已经固化,自然看不见A的新版本 事务B用了
SELECT ... LOCK IN SHARE MODE
或
SELECT ... FOR UPDATE
——这是当前读,会跳过MVCC走聚簇索引最新版,但如果A还没提交,B会被阻塞;若A已提交,B应该能看到,看不到多半是锁冲突或死锁回滚了 检查是否意外开启了
AUTOCOMMIT=0
且忘了
COMMIT
,或者客户端连接复用导致事务未真正结束 MVCC本身不保证“立即可见”,它只保证“按事务视图一致地可见”。真正影响“能不能读到”的,是Read View生成时刻、事务状态、以及你发的是快照读还是当前读——这点最容易被忽略。

相关文章