ReadView 可见性判断
候选人小张在蚂蚁金服面试中,被追问到 MVCC 的底层实现:
"ReadView 是怎么判断一个数据版本对当前事务可见的?"
小张说:"通过事务 ID 来判断,如果事务 ID 比当前事务小就能看到。"
面试官追问:"那如果数据版本的事务 ID 是 50,但当前活跃事务列表里有 [20, 30, 80],你觉得 50 可见吗?"
小张开始算:50 比 20 和 30 大,比 80 小...到底看不看到?
小张卡住了。
【面试官心理】 这道题我用来测试候选人对 ReadView 可见性算法的理解深度。能背出判断规则的占 30%,能正确应用规则的占 10%,能画出完整判断流程的占 5%。ReadView 是 MVCC 的核心,能答对这道题的候选人基本都看过源码。
一、ReadView 的数据结构 🔴
1.1 源码结构
1.2 关键字段的含义
1.3 为什么需要这些字段
二、可见性判断算法 🔴
2.1 判断规则(源码逻辑)
2.2 判断流程图
2.3 回答开篇那道题
三、RC 和 RR 的 ReadView 差异 🔴
3.1 Repeatable Read:事务开始时创建
3.2 Read Committed:每次读取都创建
【面试官心理】 这是 MVCC 最核心的差异。能讲清楚 RC 每次读都生成新 ReadView,RR 只生成一次的候选人,基本都理解 MVCC 的本质。
四、实际例子 🟡
4.1 完整时间线
4.2 幻读场景分析
五、ReadView 的清理 🟡
5.1 什么时候可以清理 ReadView
当一个事务提交后,如果没有任何其他事务的 ReadView 还需要看到它的版本,这个 ReadView 就可以清理了。
5.2 purge 操作
MySQL 后台线程定期清理不再需要的 undo log 页面:
⚠️
长事务会导致 undo log 无法清理,持续膨胀。这是生产环境中非常常见的问题。
【面试官心理】 能答出 ReadView 清理时机和 purge 机制的人很少。能说到 undo log 膨胀问题的,基本都有生产问题排查经验。
六、面试追问链
第一层:ReadView 有哪些字段?
- 候选人:m_ids, m_up_limit_id, m_low_limit_id, m_creator_trx_id
第二层:可见性判断规则是什么?
- 候选人:小于 m_up_limit_id 可见,大于等于 m_low_limit_id 不可见,在 m_ids 中不可见
第三层:RC 和 RR 的区别是什么?
- 候选人:RC 每次读都生成新 ReadView,RR 只生成一次
第四层:为什么 purge 线程需要知道 ReadView 的状态?
- 候选人:只有当没有任何 ReadView 需要看到某个 undo 版本时,才能清理