文章目录
-
-
- 第一部分:底层实现的三大支柱
-
- [1. 隐藏字段(数据在哪)](#1. 隐藏字段(数据在哪))
- [2. Undo Log 版本链(历史怎么找)](#2. Undo Log 版本链(历史怎么找))
- [3. Read View(看哪一条)](#3. Read View(看哪一条))
- 第二部分:可见性判断逻辑(核心算法)
- [第三部分:面试进阶------RC 与 RR 的区别](#第三部分:面试进阶——RC 与 RR 的区别)
- 面试话术示例(满分回答)
- [💡 小贴士](#💡 小贴士)
-
在面试中聊 MVCC(Multi-Version Concurrency Control,多版本并发控制) ,你不能只背定义。面试官想看的是你能不能把"它是怎么工作的"和"为什么它能提高并发"这两件事讲透。
简单一句话概括:MVCC 是一种通过维护数据的多个快照版本,让"读-写"操作不再互相阻塞,从而提升数据库并发性能的机制。
第一部分:底层实现的三大支柱
在面试时,建议按照"数据存哪 → 历史怎么找 → 看哪一条"的逻辑来回答。
1. 隐藏字段(数据在哪)
InnoDB 在表的每一行数据后面,都偷偷加了两个关键的隐藏列:
DB_TRX_ID:记录最后一次修改该行的事务 ID。DB_ROLL_PTR:回滚指针 ,指向该行数据存在undo log里的上一个版本。
2. Undo Log 版本链(历史怎么找)
每当你更新一条记录,旧的数据并不会被物理删除,而是被塞进 undo log 里。隐藏字段里的回滚指针会将这些旧版本串联起来,形成一条版本链。
3. Read View(看哪一条)
这是 MVCC 的"指挥官"。当你执行 SELECT 时,InnoDB 会生成一个 Read View(读视图),它像一张当前活跃事务的"系统快照",包含:
- m_ids:当前系统里还没提交的事务 ID 列表。
- min_trx_id :
m_ids里最小的 ID。 - max_trx_id:系统即将分配给下一个事务的 ID。
第二部分:可见性判断逻辑(核心算法)
这是面试的高潮部分。你需要描述事务是如何顺着"版本链"寻找自己能看的数据的:
- 拿起版本链中最新记录的
trx_id。 - 如果
trx_id < min_trx_id:说明这个版本在你开启查询前就提交了,可见。 - 如果
trx_id >= max_trx_id:说明这个版本是在你开启查询后才生成的,不可见。 - 如果在两者之间 :检查
trx_id是否在m_ids列表里。- 如果在:说明事务还没提交,不可见。
- 如果不在:说明事务已经提交,可见。
- 不可见怎么办? 顺着回滚指针去找上一个版本,重复上述判断。
第三部分:面试进阶------RC 与 RR 的区别
这是面试官最喜欢的"陷阱题"。MVCC 是如何实现不同隔离级别的?
- RC(读已提交) :事务中每一次
SELECT都会重新生成一个 Read View。所以如果你在两次查询之间有别人提交了,你能看到最新的。 - RR(可重复读) :事务中只有第一次
SELECT会生成 Read View,之后整个事务都复用这一个。所以不管别人怎么改,你看到的永远是初恋的样子。
面试话术示例(满分回答)
面试官:讲讲你对 MVCC 的理解。
你:MVCC 是 InnoDB 实现"读-写"并发的核心。它的底色是"空间换时间",让读操作不加锁,也就是我们常说的"快照读"。
实现上,它主要靠三样东西:
- 隐藏列:存事务 ID 和回滚指针。
- Undo Log:形成数据的历史版本链。
- Read View:这是一套可见性算法。
核心逻辑就是当一个事务去读数据时,它会生成一个 Read View。然后顺着 Undo Log 的版本链,用自己的 Read View 规则去比对每个版本的事务 ID。
如果是 RC 级别 ,它每次查都生成新视图,所以会发生不可重复读;如果是 RR 级别,它整个事务只在第一次查询时生成视图,从而保证了可重复读,并且在很大程度上避免了幻读。
💡 小贴士
如果面试官问:"MVCC 能完全解决幻读吗?"
你要严谨一点:不能完全解决。 它能解决"快照读"下的幻读,但如果发生了"当前读"(比如执行了 SELECT ... FOR UPDATE),还是需要靠 Next-Key Lock(记录锁+间隙锁) 来封印。