MySQL是如何实现读已提交和可重复读的——MVCC原理
先来看一下MySQL的事务隔离级别:
隔离级别 |
脏读 |
不可重复读 |
幻读 |
读未提交 |
有 |
有 |
有 |
读已提交 |
无 |
有 |
有 |
可重复读 |
无 |
无 |
有 |
串行化 |
无 |
无 |
无 |
MySQL有四种隔离级别:读未提交、读已提交、可重复读和串行化,它们分别用来解决脏读、不可重复读和幻读的问题。
脏读:一个事务读取到另一个事务还未提交的数据。
不可重复读:在一个事务中多次读取同一个数据时,结果出现不一致。
幻读:在一个事务中使用相同的 SQL 两次读取,第二次读取到了其他事务新插入的行。
直接进入本文主题——MySQL是如何实现读已提交和可重复读的?答案是MVCC,即通过多版本并发控制来实现,下面来看看什么是多版本并发控制。
在理解MVCC原理之前需要先了解两个重要概念:版本链、ReadView。
1、版本链
在InnoDB引擎中,每行记录的后面会保存两个隐藏的列:trx_id、roll_pointer。它们的作用如下:
- trx_id:用于保存每次对该记录进行修改的事务的id。
- roll_pointer:存储一个指针,指向这条数据记录上一个版本的地址,可以通过它获取到该记录上一个版本的数据信息。
比如数据库表中现在有下面一条数据:
id |
blogName |
trx_id(隐藏列) | roll_pointer(隐藏列) |
1 |
齐天小圣1号 |
10 |
现在有一个事务id为20的事务修改了这条记录,将blogName字段修改为了“齐天小圣2号”,那么这条数据被修改后将会变成下面这样:
当数据的修改次数增多,对应的版本也会随之增多,但各个版本之间通过指针相连,形成版本链的概念。
2、ReadView
MySQL中实现读已提交和可重复读的区别就在于它们生成的ReadView的策略不同。ReadView中主要就是有个列表存储着我们系统中当前活跃着的读写事务,即begin了但还未提交的事务。
那么存储这个列表有什用呢?比如当前ReadView的列表中存储着两条活跃的事务,它们的id分别为20和40:{20,40},有如下规则:
- 若某事务试图去访问id为10对应的版本数据,它比列表中最小的事务id20还要小,说明它在很早之前就提交了,那么这个id为10的事务对应的版本数据是可以访问的。
- 若某事务试图去访问id为30对应的版本数据,它大小介于列表中活跃事务id之间,此时就要判断它是否在列表中,若在,则说明还未提交不能访问,若不在,则说明已经提交可以访问。
- 若某事务试图去访问id为50对应的版本数据,它比列表中最大的事务id40还大,说明它是在生成ReadView之后才发生的,可能还没提交,所以不能访问。
3、原理
下面举个例子来说明在读已提交和可重复读两种隔离级别下MVCC的原理并比较两者的差异。
假如现在事务20将数据进行修改,但还未提交,那么版本链如下图所示,ReadView中列表为{20}。
此时另一个事务A试图查询id为1的数据,那么进入版本链首先肯定看到最近的一个版本,对应的事务id为20,按照上面的规则,发现20还在列表之中,说明id为20的事务还未提交,那么不能访问这个版本,根据指针找到上一个版本,对应的事务id为10,小于列表中的事务id,说明这个版本很早之前就提交了,那么可以访问,事务A最终查询到blogName为齐天小圣1号。
继续,现在把事务20进行提交,并新建事务30将数据进行修改但不提交,那么版本链如图所示。
现在事务A又来查询该条数据了,下面将是读已提交和可重复读两种隔离级别的区别!
假如现在隔离级别是读已提交,那么重新生成ReadView,列表为{30},事务A通过版本链找到这条数据的最近一个版本,对应的事务为30,同样依据之前的规则进行分析,30还在列表中未提交,那么这个版本不可访问,继续找到上一个版本,对应的事务id为20,小于列表中的事务id,说明这个版本很早之前就提交了,那么可以访问,事务A最终查询到blogName为齐天小圣2号。可以看到最终读到的是已提交的最新的内容,这就是读已提交。
假如现在隔离级别可重复读,那么不需要重新生成ReadView,而是继续使用之前的ReadView,列表还为{20},事务A通过版本链依次找到事务id30、20对应的数据,但是按照上面的规则,这两个版本都不能访问,直到找到事务id10对应的数据,按照规则可以访问该版本,事务A最终查询到blogName为齐天小圣1号。事务A第一次查询时也是查询到齐天小圣1号,这就实现了可重复读。
4、总结
最后比较这两种隔离级别的区别,发现根本在于它们生成ReadView的策略不同,读已提交每次查询时都会生成一个新的ReadView,而可重复读每次查询都复用第一次生成的ReadView,然后分别按照ReadView的访问规则最终实现读已提交和可重复读。
MySQL是如何实现读已提交和可重复读的——MVCC原理相关推荐
- mysql的读已提交和可重复读(Read Committed和Repeatable Read隔离级别)
1.共享锁和排他锁 1.1.共享锁 1.2.排他锁 1.3.总述 2.MVCC 2.1.隐藏字段 2.2.Read View 2.3.Undo log 2.4.update的具体流程 2.5.可见性比 ...
- MVCC如何实现数据库读已提交和可重复读这两种隔离级别?
文章目录 隐藏列 undo log ReadView 读已提交和可重复读的实现 我们都知道Mysql有四种事务隔离级别: 读未提交 读已提交 可重复读 串行化 这四个隔离级别的特点就不多赘述了,这次主 ...
- mysql读提交和重复读区别_读已提交和可重复读的区别 命令行测试
可重复读:两个事务进行数据操作他们是互不干扰的 ,事务先A进行数据查询,事务B进行一次事务修改并进行数据提交,事务A再进行一次查询,数据是不改变的. 读已提交:两个事务进行数据操作,事务先A进行数据查 ...
- mysql 读已提交、可重复读原理(mvcc、readview)
https://blog.csdn.net/qq_41388308/article/details/88583968 readview的文章https://baijiahao.baidu.com/s? ...
- MySQL数据库中,在读已提交和可重复读这两个不同事务隔离级别下幻读的区别
目 录 1. 前 言 1.1 并发事务存在的问题 1.2 事务的隔离级别 1.3 快照读和当前读 2. 不同事务隔离级别下幻读的区别 2.1 读已提交下的幻读 2.2 可重复读下的幻读 2.2.1 情 ...
- 数据库基础知识点-事务隔离级别区分(读未提交、读已提交和可重复读)
事务隔离级别 数据库事务隔离级别分4个: 读未提交-Read uncommitted 读已提交-Read committed 可重复读-Repeatable read–MySQL 序列化-Serial ...
- 看完这篇文章,让你彻底理解事务隔离级别(读未提交、读已提交、可重复读、序列化)
对于不同的事务,采用不同的隔离级别分别有不同的现象.主要有下面3种: 1.脏读(dirty read):一个事务可以读取另一个尚未提交事务的修改数据. 2.不可重复读(nonrepeatable re ...
- 遇到数据库隔离性问题(读已提交和可重复读、可重复读导致调息前后两次查询数据一样)
最近负责的Libor自动调息整个流程终于完成啦,在最后生产库执行的时候却出现了问题 纠结问题: 在调息(调整利息)之后前后数据肯定会出现变化,在测试库测试的时候,测试数据前后也出现了变化,在页面也是正 ...
- Mysql学习笔记之事务详解(读未提交、读以提交、可重复读、串行化读)
文章目录 1.事务概述 2.事务特性 3.事务隔离级别 4.演示事务 4.1.演示读未提交 4.2.演示读已提交 4.3.演示可重复读 4.4.演示串行化读 1.事务概述 什么是事务? 一个事务是一个 ...
最新文章
- Spring Cloud构建微服务架构:分布式服务跟踪(抽样收集)【Dalston版】
- LCA 在线倍增法 求最近公共祖先
- ssl1236-逃亡准备【dp之多重背包】
- 阿里技术专家推荐的20本书,免费送!
- performance and scalability
- 【异或交换原理】按位进行异或操作,实现数的交换
- OpenGL之利用模型视图矩阵和投影矩阵让球体自动旋转
- .NET Core 3.1通用主机原理及使用
- Maven(五)使用Nexus搭建Maven私服
- ppt流程图字体太小_简单三步,用WPS轻松完成一个又大气又好看的流程图!
- centos 关闭开启防火墙
- linux导出Excel The maximum column width for an individual cell is 255 characters
- react学习系列3 使用koa-router模拟后台接口
- 【优秀作业】人工鱼群优化算法
- 谈谈超平面(hyperplane)
- Java个人资产管理系统问题总结
- JZOJ5460. 【NOIP2017提高A组冲刺11.7】士兵训练
- 2019BJFU 网站设计(孙俏-web前端开发)实验代码-181002222
- 如何在家免费使用知网?
- 飞猪平台用户行为分析—python