ToB企服应用市场:ToB评测及商务社交产业平台

标题: MVCC - Read View的可见性判断理解 [打印本页]

作者: 九天猎人    时间: 2022-8-26 06:24
标题: MVCC - Read View的可见性判断理解
读了 @SnailMann大佬【MySQL笔记】正确的理解MySQL的MVCC及实现原理 收益颇丰,非常感谢!
但对其中如何判断事务是否可见性还是不太理解,于是作了本文,在原博客基础上,举例画图论证、理解了Read View的可见性判断。
引用 @SnailMann大佬【MySQL笔记】正确的理解MySQL的MVCC及实现原理 的字段说明。
隐式字段

每行记录除了我们自定义的字段外,还有数据库隐式定义的 DB_TRX_ID, DB_ROLL_PTR, DB_ROW_ID 等字段
Read View 的三个全局属性

trx_list(名称我随意取的):一个数值列表,用于维护 Read View 生成时刻系统 正活跃的事务 ID 列表
up_limit_id :是 trx_list列表中事务 ID 最小的 ID
low_limit_idRead View 生成时刻系统尚未分配的下一个事务 ID ,也就是 目前已出现过的事务 ID 的最大值 + 1
为什么是 low_limit ? 因为它也是系统此刻可分配的事务 ID 的最小值
可见性判断逻辑

针对上面三种情况,下面举例说明:
原记录:amount = 100
事务1事务2事务3事务4开启事务开启事务开启事务update amount = 200update amount = 300提交事务①select amount; 开始快照读,生成Read View提交事务开启事务②select amount;update amount = 400;提交事务③select amount;请问三次select amount; 快照读到的值分别是多少,为什么?
画一张图,把undo表里存的记录版本链及当前记录画出来。


1>如图,当前行 DB_TRX_ID(1)  == up_limit_id(1),说明本次修改该记录的事务正在进行中,也就是事务1还未结束,事务2就应该对事务1这次修改不可见,可见就是脏读了。
2>当前记录不可见,再根据回滚指针追踪到上个版本记录,如图undo日志内 金额为200的行,此时再通过Read View进行可见性判断。
第一种情况:当前行 DB_TRX_ID(3)  > up_limit_id(1),不确定;
第二种情况:DB_TRX_ID(3) < low_limit_id(4),也不确定;
第三种情况:DB_TRX_ID(3)不在trx_list中,不是活跃的事务,说明事务3在事务2生成Read View之前就已经提交,那么是可见的。
所以读取的金额为200。

事务1提交事务,不过undo表与当前行数据无变化,对事务1的Read View的数据也不会变化,因为RR模式下,Read View 只会在第一次快照读时生成,后面几次快照读不会生成新的 Read View,也不会改动之前Read View的值。
当前行数据与Read View 都无变化,那么可见性判断也同①一致,读取到的金额为200。

第一种情况:当前行 DB_TRX_ID(4)  > up_limit_id(1),不确定;
第二种情况:DB_TRX_ID(4) > low_limit_id(1),说明当前行是被生成Read View之后出现的事务修改的,这种未来的数据肯定是不可见的。
再接着追溯,就与①中追溯的过程相差不大了,最终读取的金额也是为200。
总结

这里举例论证了可见性判断的合理性,总结来说,可见性的三个判断约束了一件事,只有在本事务生成Read View之前就已经提交的事务的修改才可以被看见,其他的无论是正在进行的事务的修改还是之后再提交的事务的修改都不可见

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4