MySQL read view 在RR和RC隔离级别下的异同
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隔离级别下的异同的更多相关文章
- [原创]MySQL RR隔离级别下begin或start transaction开启事务后的可重复读?
Server version: 5.6.21-log MySQL Community Server (GPL) 前提提要: 我们知道MySQL的RR(repeatable read)隔 ...
- InnoDB在MySQL默认隔离级别下解决幻读
1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...
- 【MySQL 读书笔记】RR(REPEATABLE-READ)事务隔离详解
这篇我觉得有点难度,我会更慢的更详细的分析一些 case . MySQL 的默认事务隔离级别和其他几个主流数据库隔离级别不同,他的事务隔离级别是 RR(REPEATABLE-READ) 其他的主流数据 ...
- [高性能MYSQL 读后随笔] 关于事务的隔离级别(一)
一.锁的种类 MySQL中锁的种类很多,有常见的表锁和行锁,也有新加入的Metadata Lock等等,表锁是对一整张表加锁,虽然可分为读锁和写锁,但毕竟是锁住整张表,会导致并发能力下降,一般是做dd ...
- Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)
Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...
- MySQL Transaction--RR事务隔离级别下加锁测试
============================================================================== 按照非索引列更新 在可重复读的事务隔离级别 ...
- MySQL Transaction--RC事务隔离级别下加锁测试
==============================================================================非索引列更新 在读提交的事务隔离级别下,在非 ...
- InnoDB MVCC RR隔离级别下的数据可见性总结
一.背景 熟悉数据库隔离级别的人都知道,在RR(可重复读)隔离级别下,无论何时多次执行相同的SELECT快照读语句,得到的结果集都是完全一样的,即便两次SELECT语句执行期间,其他事务已经改变了该查 ...
- MySQL(24):事务的隔离级别
1. 事务的隔离级别引入: 数据库是多线程并发访问的,所以很容易出现多个线程同时开启事务的情况,这样的就会出现脏读.重复读以及幻读的情况.在数据库操作中,为了有效保证并发读取数据的正确性,需要为事务设 ...
- mysql中不同事务隔离级别下数据的显示效果--转载
事务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查询语句因为崩溃或其他原因而无法执行,那么所有的语句就都 ...
随机推荐
- vulnhub - LAMPSECURITY: CTF5
vulnhub - LAMPSECURITY: CTF5 信息收集 端口扫描 nmap -sT --min-rate 10000 -p- 192.168.157.164 详细扫描 sudo nmap ...
- Spring常见面试题总结
Spring是什么? Spring是一个轻量级的IoC和AOP容器框架.是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求.常见的配置方式有 ...
- windows 安装fvm 安装使用FVM,管理多版本flutter
背景:win10 1,先用clash代理powershell命令,解决网络问题 2.使用dart 安装FVM dart pub global activate fvm 3.安装后检查系统环境变量 3. ...
- Kafka消费端抛出异常Offset commit cannot be completed since the consumer is not part of an active group for auto partition assignment; it is likely that the consumer was kicked out of the group的解决方案
总结/朱季谦 在一次测试Kafka通过consumer.subscribe()指定偏移量Offset消费过程中,因为设置参数不当,出现了一个异常提示-- [2024-01-04 16:06:32.55 ...
- MySQL派生表合并优化的原理和实现
本文分享自华为云社区<[华为云MySQL技术专栏]MySQL 派生表合并优化的原理和实现>,作者:GaussDB 数据库. 引言 MySQL是一种流行的开源关系型数据库管理系统,广泛应用于 ...
- webpack4.15.1 学习笔记(二) — 配置及开发环境构建
目录 基本安装 配置文件 管理资源 管理输出 构建一个开发环境 使用 source map 选择一个开发工具 观察模式 webpack-dev-server webpack-dev-middlewar ...
- TIER 0: Redeemer
TIER 0: Redeemer Redis Remote Dictionary Server 是一个开源的内存数据存储系统 Redis 是完全基于 内存,"内存"数据库的数据检索 ...
- python raise异常处理
python raise异常处理 一般最简单的异常处理是try except: try: f = open('test.txt') except Exception as e: print(e) f ...
- app专项测试:app弱网测试
app专项测试:app弱网测试 弱网测试背景 用户体验 APP使用过程中,弱网的高延迟和高丢包,在实时性要求非常高的场景,容易伤害用户体验 非正常情况下,Bug出现几率会增加 在解决日常支持需求中,经 ...
- 【SqlServer】02 SSMS工具基本使用入门
之前的安装中除了SqlServer,还有一个SSMS管理工具 数据库的访问依赖于工具 SSMS提供了两种登陆方式: 创建用户: 删除用户: 创建数据库: 删除数据库: 创建表: 设置表的字段,字段名称 ...