REJAVA / LEARNING NOTES
第12课速查:MVCC(多版本并发控制)与可见版本
随时回查术语、规则和示例;完整解释见对应课程。
根据课程材料整理
本次更新说明
- 整理为公开学习笔记,保留要点、对照表与练习入口。
一行数据为什么能读出旧值
当前聚簇索引记录上的 DB_TRX_ID(最近修改事务编号)标识修改者,DB_ROLL_PTR(回滚指针)指向撤销记录。undo log(撤销日志)保存还原旧行所需的信息;顺着这些信息逐步还原,形成逻辑上的 version chain(版本链)。不是每个事务各复制一张表,也不保证所有历史永远保留。
按这四步找可见版本
范围:普通一致性读,已有记录的更新;从当前版本开始检查。Read View(读视图)保存建立时的活跃读写事务名单、上下边界和创建者信息。
- 自己的修改:可见。
- 其他修改者编号小于下边界:可见。
- 其他修改者编号大于或等于上边界:不可见。
- 处于两边界之间:在建立时名单里不可见,不在则可见。
不可见就沿撤销信息还原上一个版本;找到第一个可见版本即停止。编号是修改事务编号,不是业务主键或提交顺序。旧名单不因别人后来提交而刷新。
用一个例子连起来
A只读,在同一可重复读事务复用旧视图:下边界100、上边界110、名单100和105。100改别的记录;103已提交;105在视图建立时未提交,后来提交,再由112修改并提交。有效版本链从新到旧为112写13→105写11→103写9。
| 版本 | 为什么 | 动作 |
|---|---|---|
| 112写13 | 112≥110 | 不可见,往旧找 |
| 105写11 | 在旧名单里 | 不可见,往旧找 |
| 103写9 | 100≤103<110,且不在名单里 | 返回9,停止 |
若另一查询明确使用新视图:名单100,下边界100、上边界113,则112版本可见,返回13。这里的编号是假设,不是数据库实测输出。
何时换视图
- READ COMMITTED(读已提交):每次普通一致性读使用新的快照。
- REPEATABLE READ(可重复读):同一事务复用首次一致性读建立的快照。
普通开始事务不等于立即建立快照;自己的写入仍可见。以上不是锁定读和写操作的完整规则。
容易漏的边界
- 写事务提交后,旧视图可能仍需 update undo(更新撤销信息)。满足清理条件后,由 purge(历史清理)后台处理。
- 长时间保留旧视图可能拖住历史清理。查询完成后及时结束事务,避免开着事务等待用户操作。
- 快照读不阻止别人审批;并发审批需要合适的锁或条件更新,并检查执行结果。
- 活跃名单为空仍有上边界,未来的其他事务版本不会因此全部可见。
源码对照(mysql-8.4.0):m_up_limit_id是可见性下边界,m_low_limit_id是可见性上边界。名字容易记反,本课不要求背字段名。
复习与主来源
遮住例子,先自己说112、105、103各自怎样判断;隔日换编号再做。能跟着答案读懂,不等于能独立讲清楚,也不等于隔几天还记得。
主读官方多版本存储,配读一致性非锁定读;精确可见性判断见固定版本源码。有疑问时,先写清具体版本链和视图,再回到课程第三、四节逐步核对。