MVCC - Read View的可见性判断理解
读了 @SnailMann大佬【MySQL笔记】正确的理解MySQL的MVCC及实现原理 收益颇丰,非常感谢!
但对其中如何判断事务是否可见性还是不太理解,于是作了本文,在原博客基础上,举例画图论证、理解了Read View的可见性判断。
引用 @SnailMann大佬【MySQL笔记】正确的理解MySQL的MVCC及实现原理 的字段说明。
隐式字段
每行记录除了我们自定义的字段外,还有数据库隐式定义的 DB_TRX_ID, DB_ROLL_PTR, DB_ROW_ID 等字段
DB_TRX_ID
6 byte,最近修改(修改/插入)事务 ID:记录创建这条记录/最后一次修改该记录的事务 IDDB_ROLL_PTR
7 byte,回滚指针,指向这条记录的上一个版本(存储于 rollback segment 里)DB_ROW_ID
6 byte,隐含的自增 ID(隐藏主键),如果数据表没有主键,InnoDB 会自动以DB_ROW_ID产生一个聚簇索引
Read View 的三个全局属性
trx_list(名称我随意取的):一个数值列表,用于维护Read View生成时刻系统 正活跃的事务 ID 列表
up_limit_id:是trx_list列表中事务 ID 最小的 ID
low_limit_id:Read View生成时刻系统尚未分配的下一个事务 ID ,也就是 目前已出现过的事务 ID 的最大值 + 1
为什么是low_limit? 因为它也是系统此刻可分配的事务 ID 的最小值
可见性判断逻辑
DB_TRX_ID < up_limit_id, 当前行事务id比活跃的最小事务id还小时,说明了两件事,当前行事务对该记录的修改已经提交,因为当前事务id比活跃的最小事务id还小,不在活跃的事务之中,也就意味着该事务已经提交或回滚,这时因为已经成功修改,那么应该就是提交成功了。
也就是在生成Read View之前,事务已经提交,接下来判断
DB_TRX_ID >= low_limit_id, 修改该行的事务id大于了Read View里系统待分配的下一个事务id,说明修改该行的事务是生成该Read View之后出现的事务,因为Read View系统待分配的下一个事务id被用了,才会出现比该事务id大的事务。这时,也应该是不可见的,一个事务怎么可以看到后面新来事务做的修改了。判断
DB_TRX_ID是否在活跃事务之中,trx_list.contains (DB_TRX_ID),如果在活跃事务之中,说明该修改是其他事务未提交的修改,应该是不可见的,如果可见就是脏读了,如果不在活跃事务之中,说明在生成Read View之前,该事务的修改就已提交,与第一个判断逻辑类似,事务2是可以查到这条记录的。
针对上面三种情况,下面举例说明:
原记录:amount = 100
| 事务1 | 事务2 | 事务3 | 事务4 |
|---|---|---|---|
| 开启事务 | 开启事务 | 开启事务 | |
update amount = 200 |
|||
update 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之前就已经提交的事务的修改才可以被看见,其他的无论是正在进行的事务的修改还是之后再提交的事务的修改都不可见。
MVCC - Read View的可见性判断理解的更多相关文章
- Android检测View的可见性
Android中我们经常会用到判断View的可见行,当然有人会说View.VISIBLE就可以了,但是有时候这个真是满足不了,有时候我们为了优化,在View滚到得不可见的时候或者由于滚到只显示了部分内 ...
- [转]Android View.onMeasure方法的理解
转自:http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html Android View.onMeasure方法的理解 View在屏幕上显示出来要先经过 ...
- jvm的可见性的理解
同步包括两方面的含义: 独占性和可见性. 很多人仅仅理解了独占性,而忽略了可见性. 根据Java Language Specification中的说明, jvm系统中存在一个主内存(Main Memo ...
- 【view绘制流程】理解
一.概述 View的绘制是从上往下一层层迭代下来的.DecorView-->ViewGroup(--->ViewGroup)-->View ,按照这个流程从上往下,依次measure ...
- 页面可见性判断:document.hidden与visibilitychange事件
我们需要在特定的时候判断页面的显示状态,例如:当视频加载到可播放状态时,根据用户是否停留在当前页面来决定是否开始自动播放.页面的展示的状态的判断就需要用到html5新增的一个api:document. ...
- android之对于view的一点深入理解
最近在写程序中,遇到了之前自己没遇到过的代码,一番理解后才知道原来是在动态设定xml布局中的属性.即利用LayoutParams可以动态的设定布局或者控件的宽和高,以及的它的左间距,右间距,内间距,和 ...
- 谈谈我对MVC的View层实现的理解
MVC框架可以把应用清晰明了地分为三个部分:Model层–数据层,View层–视图层,Controller–逻辑层,Model层负责整合数据,View层负责页面渲染,Controller层负责实现业务 ...
- Android View.onMeasure方法的理解
View在屏幕上显示出来要先经过measure(计算)和layout(布局).1.什么时候调用onMeasure方法? 当控件的父元素正要放置该控件时调用.父元素会问子控件一个问题,“你想要用多大地方 ...
- [转载]Android View.onMeasure方法的理解
2013-12-18 10:56:28 转载自http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html View在屏幕上显示出来要先经过measure( ...
随机推荐
- XCTF练习题---MISC---embarrass
XCTF练习题---MISC---embarrass flag:flag{Good_b0y_W3ll_Done} 解题步骤: 1.观察题目,下载附件,这道题真难 2. 拿到手以后默认使用Wiresha ...
- [AcWing 800] 数组元素的目标和
点击查看代码 #include<iostream> using namespace std; const int N = 1e5 + 10; int a[N], b[N]; int mai ...
- C#自定义配置文件(一)
C#自定义配置文件 .NET程序中,经常使用Config文件来配置应用程序中经常使用的值,比如数据库连接字符串.最近项目遇到一个需要配置好多节点在配置文件中的需求.为了使配置节点整洁易维护,在代码调用 ...
- Windows平台安装SQLite3数据库
Windows平台安装SQLite3数据库 话不多说,开始! 访问SQLite官网下载资源 在搜索引擎中键入SQLite3关键字寻找官网入口或直接点击此处前往SQLite官网,官网界面如下: 点击页面 ...
- [题解] [AGC022E] Median Replace
题目大意 有个奇数长度的 \(01\) 串 \(s\) 其中有若干位置是 \(?\). 每次可将 \(3\) 个连续的字符替换成这三个数的中位数. 求有多少方案将 \(?\) 替换成 \(0/1\) ...
- 团队Beta4
队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 **过去两天完成了哪些任务 ** 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 无 接下来的计划 完成短租车,页面美化 * ...
- 在GO中调用C源代码#基础篇1
开坑说明 最近在编写客户端程序或与其他部门做功能集成时多次碰到了跨语言的sdk集成,虽说方案很多诸如rpc啊,管道啊,文件io啊,unix socket啊之类的不要太多,但最完美的基础方式还是让程序与 ...
- form表单,css简介,css选择器,css样式操作
form表单 简介 表单在Web网页中用以让访问者输入数据,当提交表单时,表单中输入的数据被打包传递给Web服务器端的程序 以处理,从而使得Web服务器与用户之间具有交互功能. 表单实现前后台交互:用 ...
- [保姆级教程] 如何在 Linux Kernel (V5.17.7) 中添加一个系统调用(System call)
最近在学习 <linux Kernel Development>,本书用的linux kernel 是v2.6 版本的.看完"系统调用"一节后,想尝试添加一个系统调用, ...
- 由C# dynamic是否装箱引发的思考
前言 前几天在技术群里看到有同学在讨论关于dynamic是否会存在装箱拆箱的问题,我当时第一想法是"会".至于为啥会有很多人有这种疑问,主要是因为觉得dynamic可能是因为有点特 ...