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( ...
随机推荐
- 服务器BIOS和BMC等知识详解
一个执着于技术的公众号 引言:以BIOS为核心的固件产业,是信创产业链的重要组成部分,可被誉为信创产业的"山海关".在计算机体系中,BIOS 有着比操作系统更为底层和基础性的作用, ...
- C#中的接口和类有什么异同
不同点: 1. 不能直接实例化接口 2. 接口中的成员不能用访问修饰符修饰(默认public) 3. 接口不包含方法的实现 4. 接口可以多继承,类只能单继承. 5. 类定义可在不同的源文件之间进行拆 ...
- CRM项目的整理---第一篇
CRM:cunstomer relationship management 客户管理系统 1.项目的使用者:销售 班主任 讲师 助教 2.项目的需求分析 2.1.注册 2.2.登录 2.3 ...
- 27个常用Linux命令
1.查找文件 find / -name filename.txt 根据名称查找/目录下的filename.txt文件. 2.查看一个程序是否运行 ps –ef|grep tomcat 查看所有有关to ...
- SpringBoot Redis 实践指南
前言 SpringBoot Cache 是一个很好的缓存框架,可以兼容多种缓存实现,数据量较大的情况下,Redis 应该是最多被使用的. 本文重点介绍 SpringBoot 和 Redis 整合使用的 ...
- linux篇-linux修改网卡名(亲测有效)
1查看网卡ip addr 2cd /etc/sysconfig/network-scripts Ls查看 3mv ifcfg-eno16777736 ifcfg-eth0重命名,然后编辑 最后一行加入 ...
- 搭建NTP时间服务器~使用NTP同步时间~构建主机间时间自动同步关系
NTP是一个时间服务器,同时它也是一个时间客户端. 我们可以使用它构建主机与主机之间的时间自动同步环境,保证所有服务器时间一致性. 常用的公共NTP时间服务器有: cn.ntp.org.cn 中国 n ...
- 论文阅读 Predicting Dynamic Embedding Trajectory in Temporal Interaction Networks
6 Predicting Dynamic Embedding Trajectory in Temporal Interaction Networks link:https://arxiv.org/ab ...
- Android 子线程 UI 操作真的不可以?
作者:vivo 互联网大前端团队- Zhang Xichen 一.背景及问题 某 SDK 有 PopupWindow 弹窗及动效,由于业务场景要求,对于 App 而言,SDK 的弹窗弹出时机具有随机性 ...
- javaweb开发案例
1.实验3 (1)当运行Servlet时,碰到"空指针异常"错误怎么处理? 答:应提示用户操作有误,或设置对象值为空字符串或一个默认值,或是不执行某操作,直接跳转到其他处理中. ( ...