1.首先了解下什么是read view

这里说的 read view 是InnoDB 在实现 MVCC 时用到的一致性读视图,即 consistent read view,用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现。 
read view 并没有物理结构,作用是事务执行期间用来定义"我能看到什么数据"。

2.事务id

InnoDB 里面每个事务有一个唯一的事务 ID,叫做 transaction id。它是在事务开始的时候向 InnoDB 的事务系统申请的,是按申请顺序严格递增的。 
在innodb存储引擎下,聚簇索引记录中都包含两个必要的隐藏列: 
trx_id:每次对某条记录进行改动时,对会把对应的事务id赋值给trx_id隐藏列; 
roll_pointer:每次对某条记录进行改动时,这个隐藏列会存一个指针,可以通过这个指针找到该记录修改前的信息,也就是undo回滚段中的内容。

3.RR(Repeatable Read,可重复读)隔离级别下的实现

在可重复读隔离级别下,事务在启动的时候就"拍了个快照"。注意,这个快照是基于整库的。 
以一个事务启动的时刻为准,如果一个数据版本是在这个事务启动之前生成的,就可以看到;如果是在这个事务启动以后才生成的,就看不到,就必须要找到它的上一个版本。 
实现上,事务启动的瞬间,InnoDB 为这个事务构造了一个数组,用来保存这个事务启动瞬间,当前正在"活跃"的所有事务 ID。“活跃”指的就是,启动了但还没提交。数组里面事务 ID 的最小值记为低水位,当前系统里面已经创建过的事务 ID 的最大值加 1 记为高水位。这个视图数组和高水位,就组成了当前事务的一致性视图(read-view),不同时刻启动的事务会有不同的 read-view。

而每次事务更新数据的时候,都会生成一个新的数据版本,并且把 transaction id 赋值给这个数据版本的事务ID,记为 row trx_id。同时,旧的数据版本要保留,并且在新的数据版本中,能够有信息可以直接拿到它。 
这个read view 视图数组把所有的 row trx_id 分成了几种不同的情况:已提交事务、未提交事务集合、未开始事务。当前事务一定在低水位和高水位之间。

那么总结下来可以有几个概念就是:

m_ids:表示在生成readview时,当前系统中活跃的读写事务id数组; 
min_trx_id:表示在生成readview时,当前系统中活跃的读写事务中最小的事务id,也就是m_ids中最小的值,就是低水位; 
max_trx_id:表示生成readview时,系统中应该分配给下一个事务的id值,就是高水位; 
creator_trx_id:表示生成该readview的事务的事务id;

而数据版本的可见性规则,就是基于数据的 row trx_id 和这个一致性视图的对比结果得到的: 
1.如果被访问版本的row trx_id,与readview中的creator_trx_id值相同,表明当前事务在访问自己修改过的记录,该版本可以被当前事务访问; 
2.如果被访问版本的row trx_id,小于readview中的min_trx_id值,表明生成该版本的事务在当前事务生成readview前已经提交,该版本可以被当前事务访问; 
3.如果被访问版本的row trx_id,大于或等于readview中的max_trx_id值,表明生成该版本的事务在当前事务生成readview后才开启,该版本不可以被当前事务访问; 
4.如果被访问版本的row trx_id,值在readview的min_trx_id和max_trx_id之间,就需要判断trx_id属性值是不是在m_ids列表中, 
如果在:说明创建readview时生成该版本的事务还是活跃的,该版本不可以被访问; 
如果不在:说明创建readview时生成该版本的事务已经被提交,该版本可以被访问。

现有示例如下:

那么 事务1、事务2、事务4的查询结果是多少呢? 
事务1的两次查询结果都是 100 
事务2第一次查询是100,第二次查询是80 
事务4的第一次查询是90

这个结果是不是同你得出的结果一致呢?现在我们来解析例子中的结果: 
start transaction with consistent snapshot; 这条语句执行完就是开启了一个事务,按照可重复读的定义,一个事务启动的时候,能够看到所有已经提交的事务结果。但是之后,这个事务执行期间,其他事务的更新对它不可见。

假设在事务1之前有一个活跃事务,这个事务id是99;事务1、事务2、事务3、事务4的事务id分别是100,101,102,103;这个例子的期间没有其他事务;假设这行数据在这三个事务开始之前是row trx_id是90; 
那么: 
事务1启动的时候,read view数组中的值是[99,100] 
事务2启动的时候,read view数组中的值是[99,100,101] 
事务3启动的时候,read view数组中的值是[99,100,101,102] 
事务4启动的时候,事务3已经提交了,所以read view数组中的值是[99,100,101,103]

数据 id = 1 这条记录的数据版本如下:

从图中可以看出,第一次有效更新是事务2把(id,score) 从 (1,100)更新成了(1,90),那么此时这个数据的最新版本就变成了row trx_id 102,而trx_id 90 这个版本就成了历史版本;第二次有效更新是事务2把(id,score)从当前值(1,90)更新成了(1,80),这个数据的最新版本变成了 row trx_id 101,而trx_id 102成为了历史版本。

对于事务1来说,101就是高水位,活跃事务有[99,100],在第一次查询的时候,id=1的数据的row trx_id是90,小于read view中的最小值即低水位值99,所以此时的数据是可见的;第二次查询的时候,id=1的数据的row trx_id是101,等于read view中的高水位,数据不可见,继续往前找数据的历史版本,发现历史版本1的row trx_id是102,大于read view中的高水位,数据依然不可见,再往前找历史版本2的row trx_id是90,小于read view中的最小值即低水位值99,所以此时的数据是可见的;所以事务1两次的查询id=1的值都是100

对于事务2来说,102是高水位,活跃事务有[99,100,101],在第一次查询的时候,id=1的数据的row trx_id是102,等于read view中的高水位,数据不可见,继续往前找数据的历史版本2 row trx_id是90,小于read view中的最小值即低水位值99,所以此时的数据是可见的,第一次查询id=1结果是score=100;第二次查询的时候,id=1的数据的row trx_id是101,等于自己当前的事务id,就是说现在查询的数据的更改是自己更改的,所以查询id=1结果是score=80

事务3对数据进行了修改就提交了,对数据的修改是当前读。

对于事务4来说,104是高水位,活跃事务有[99,100,101,103],查询的时候,id=1的数据的row trx_id是101,101介于低水位和高水位之间(介于readview的min_trx_id和max_trx_id之间)且就在活跃的事务列表中,说明此时事务还没有提交,是不可见的,否则就是脏读,继续往前发现历史版本1的row trx_id是102,102介于低水位和高水位之间,但是不在活跃的事务列表中,说明此时事务已经提交,数据是可见的,所以查询id=1的结果是90

4.RC(Read Committed,读提交)隔离级别下的实现

在读提交隔离级别下,每一个语句执行前都会重新算出一个新的视图。 
在读提交隔离级别下,"start transaction with consistent snapshot;" 就等于 start transaction,start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作 InnoDB 表的语句,事务才真正启动。 
所以示例在RC隔离级别下:

事务1的第一次查询结果是100,第二次查询结果是90 
事务2第一次查询是90,第二次查询是80 
事务4的第一次查询是90

MySQL read view 在RR和RC隔离级别下的异同的更多相关文章

  1. [原创]MySQL RR隔离级别下begin或start transaction开启事务后的可重复读?

    Server version:         5.6.21-log MySQL Community Server (GPL) 前提提要: 我们知道MySQL的RR(repeatable read)隔 ...

  2. InnoDB在MySQL默认隔离级别下解决幻读

    1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...

  3. 【MySQL 读书笔记】RR(REPEATABLE-READ)事务隔离详解

    这篇我觉得有点难度,我会更慢的更详细的分析一些 case . MySQL 的默认事务隔离级别和其他几个主流数据库隔离级别不同,他的事务隔离级别是 RR(REPEATABLE-READ) 其他的主流数据 ...

  4. [高性能MYSQL 读后随笔] 关于事务的隔离级别(一)

    一.锁的种类 MySQL中锁的种类很多,有常见的表锁和行锁,也有新加入的Metadata Lock等等,表锁是对一整张表加锁,虽然可分为读锁和写锁,但毕竟是锁住整张表,会导致并发能力下降,一般是做dd ...

  5. Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)

    Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...

  6. MySQL Transaction--RR事务隔离级别下加锁测试

    ============================================================================== 按照非索引列更新 在可重复读的事务隔离级别 ...

  7. MySQL Transaction--RC事务隔离级别下加锁测试

    ==============================================================================非索引列更新 在读提交的事务隔离级别下,在非 ...

  8. InnoDB MVCC RR隔离级别下的数据可见性总结

    一.背景 熟悉数据库隔离级别的人都知道,在RR(可重复读)隔离级别下,无论何时多次执行相同的SELECT快照读语句,得到的结果集都是完全一样的,即便两次SELECT语句执行期间,其他事务已经改变了该查 ...

  9. MySQL(24):事务的隔离级别

    1. 事务的隔离级别引入: 数据库是多线程并发访问的,所以很容易出现多个线程同时开启事务的情况,这样的就会出现脏读.重复读以及幻读的情况.在数据库操作中,为了有效保证并发读取数据的正确性,需要为事务设 ...

  10. mysql中不同事务隔离级别下数据的显示效果--转载

    事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都 ...

随机推荐

  1. yb课堂之分布式应用下登陆校验解决方案 JWT讲解 json wen token 《八》

    什么是JWT? JWT是一个开放标准,它定义了一种用户简介,自包涵的用于通信双方之间以JSON对象的形式安全传递信息的方法.可以使用HMAC算法或者是RSA的公钥密钥进行签名 简单来说:就是通过一定规 ...

  2. SpringBoot配置Jackson处理字段

    常用框架 阿里fastjson,谷歌gson等 JavaBean序列化为json 性能:Jackson>FastJson>Gson>lib 同个结构 Jackson.Fastjson ...

  3. window10设置开机自启动exe的三种方式(亲测有效)

    拷贝文件到自启动位置 路径地址:C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp 通过组策略设置脚本随服务器启动 开始-> ...

  4. webpack4.15.1 学习笔记(三) — 模块热替换HMR

    目录 模块热替换 HMR HMR监听文件变化 HMR 修改样式表 模块热替换 HMR 允许在运行时更新各种模块,而无需进行完全刷新.不适用于生产环境,意味着应当只在开发环境使用.启用HMR实际上就是更 ...

  5. [WUSTCTF2020]朴实无华(命令执行)

    请求头问题 去查了一下资料了解了一下没有什莫用 robots.txt 中有东西 假flag 但是请求头里有重要消息 访问页面/fl4g.php <img src="/img.jpg&q ...

  6. [oeasy]python0016_在vim中直接运行python程序

    回忆上次内容 上次 置换 esc 和 caps lock 任何操作 都可以在 不移动 手腕的状态下完成了 每次都要 退出vim编辑器 才能 在shell中 运行python程序 有点麻烦 想要 不退出 ...

  7. [rCore学习笔记 012]彩色化LOG

    实验要求 实现分支:ch1 完成实验指导书中的内容并在裸机上实现 hello world 输出. 实现彩色输出宏(只要求可以彩色输出,不要求 log 等级控制,不要求多种颜色) 隐形要求 可以关闭内核 ...

  8. windows下mysql服务局域网访问配置

    在局域网中访问本机(Windows)的MySQL服务器,需要确保MySQL服务器配置为允许远程访问,并且防火墙设置允许外部连接.以下是详细的步骤: 1. 修改MySQL配置文件允许远程访问 找到并编辑 ...

  9. 对比python学julia(第二章)--(第三节)玫瑰曲线—数学之美

    3.1.问题描述 在数学世界中有一些美丽的曲线图形,有螺旋线.摆线.双纽线.蔓叶线且.心脏线.渐开线.玫瑰曲线.蝴蝶曲线-- 这些形状各异.简有繁别的数学曲线图形为看似枯燥的数学公式披上精彩纷呈的美丽 ...

  10. python3解析wav文件获取dtmf值

    操作系统 :Windows 10_x64 Python版本:3.9.2 从事FreeSwitch相关工作,大概率会遇得到DTMF,DTMF的传递方式有三种: In-band RFC2833 SIP-I ...