一次性掌握innodb引擎如何解决幻读和不可重复读
了解mysql的都知道,在mysql的RR(可重复)隔离级别下解决了幻读和不可重复。你知道RR下是怎么解决的吗,很多人会回答是通过MVCC和next-key解决的,具体是怎么解决的,今天来重点分析下。
mysql的隔离级别都不陌生了,简单回顾下四种隔离级别:RU(读未提交)、RC(读已提交)、RR(可重复读)【默认隔离级别】、Serializable(可串行化)。四种隔离级别控制力度有浅到深。日常的系统中常使用RC、RR两种,最常用的是RR。
一、认识两种读
说起mysql,很多人会给你说有两种读:快照读和当前读。我更喜欢在他们前面加个修饰那就是在RC、RR隔离级别下才有快照读和当前读。为什么这样说,这是因为只有在这两种隔离级别下才会有两种读。其他则是只有一种读那就是当前读。
在RU隔离级别下,不需要进行控制,可以读到其他事务未提交的事务,那肯定是当前读了。
在Serializable隔离级别下,所有的sql都会加锁,查询类型的sql加S(共享)锁、更新类型的sql加X(排它)锁。自然也都是当前读。
在RC、RR隔离级别下分别要解决脏读、幻读和不可重复读,所以才有了快照读和当前读。
关于对快照读和当前读的理解,从字面意思上理解即可,快照读也就是会读取一个快照版本,或者说历史版本;当前读就是读取当前的最新的数据。
在RU、Serializable隔离级别下,普通的select语句都是当前读;在RC、RR隔离级别下普通的select语句都是快照读。由于平时使用RR隔离级别多,所以,默认select语句都是快照读。
不论在哪种隔离级别下更新操作(insert/update/delete)都是当前读,当前读是要加锁的;下面的sql也是当前读,
select ... for update; 加X(排它)锁
select ... in share mode; 加S(共享)锁
二、认识MVCC
MVCC(Multi-Version Concurrency Control)翻译过来是多版本并发控制,存在于RC、RR隔离级别下,用于快照读。是这样来实现的,存储引擎全局维护了一个系统版本号,每开启一个新的事务,这个系统版本号就会递增。事务开始时刻的系统版本号,会作为这个事务本身的版本号。在每行记录中,存储引擎又在每行的后面保存两个隐藏的列,分别保存这一行的开始版本号(trx_id)和过期版本号(roll_pointer)。版本号就是事务ID。
看下各种更新语句版本号的情况,
insert,存储引擎为新插入的每一行保存当前的系统版本号作为这一行的开始版本号。
update,存储引擎会新插入一行记录,当前的系统版本号是新记录行的开始版本号;同时会将当前行的过期版本号设为原来行的系统版本号;
delete,存储引擎将删除的记录行的过期版本号设置为当前的系统版本号。
还要了解另外一个概念,readview。
readview用来判断版本链中哪个版本对当前事务是可见的,包含4个重要属性:
m_ids:生成ReadView时,当前系统活跃的事务id列表;
min_trx_id:列表中的最小事务id;
max_trx_id:列表中最大事务id;
creator_trx_id:生成该ReadView自身事务的id。
注意:如果一个事务只读,则creator_trx_id默认为0,只有当事务发生INSERT和UPDATE、DELETE操作时才会分配该事务id。creator_trx_id是为了判断这条undo log是否是自己生成的。
如何判断数据的可见性,
- 从记录的最新版本开始迭代依次取隐藏列trx_id和ReadView的m_ids、min_trx_id、max_trx_id比较。
- 如果trx_id等于creator_trx_id表示该版本是自己更新的,版本可见;
- 如果trx_id在m_ids列表中,则该版本不符合可见性要求;
- 如果版本trx_id小于min_trx_id,表示事务在创建ReadView时已经提交,版本可见;
- 如果版本trx_id大于max_trx_id表示,该事务是在ReadView生成之后创建和提交的,不符合可见性要求;
简单点来说,MVCC就是基于记录的事务id做控制,一条记录会有多个事务id,代表多个事务id的记录会存储在undo log中。
三、解决幻读和不可重复读
3.1、select
在RC隔离级别下,解决了脏读的情况,是怎么解决的呐,当然是通过MVCC,因为MVCC是基于事务ID,也就是trx_id,所以在select的时候读取的一定是commit之后的数据,不提交没有trx_id哦,注意在RC隔离级别下是每次select都会产生一个独立的readview,所以幻读和不可重复读是无法解决的。
在RR隔离级别下,肯定脏读是不存在的。同时解决了幻读和不可重复读,也是通过MVCC,只不过这里生成readview的时机和RC隔离级别下不一样,在RR隔离级别下readview是在事务的第一个select的时候生成的,以后的select会使用第一个select的readview,这样就可以解决了幻读和不可重复读。
3.2、update/insert/delete
update/insert/delete语句都是当前读,为什么在更新语句中会有读,这是因为在执行更新操作的时候肯定要先读出来,再进行更新,这里的读便是当前读,只不过这里的当前读在RR隔离级别下是通过加next-key解决的,所以在RR隔离级别下可以解决幻读和不可重复读。
总结
本文重点分享了mysql的innodb引擎如何解决幻读和不可重复读。重点关注两点,
1、MVCC,快照读的时候使用MVCC;
2、next-key,当前读加next-key;
推荐阅读
花了一周时间,总算把mysql的加锁搞清楚了,再也不怕间隙锁和next-key了

一次性掌握innodb引擎如何解决幻读和不可重复读的更多相关文章
- InnoDB 是如何解决幻读的
前言 大部分人在日常的业务开发中,其实很少去关注数据库的事务相关问题,基本上都是 CURD 一把梭.正好最近在看 MySQL 的相关基础知识,其中对于幻读问题之前一直没有理解深刻,今天就来聊聊「Inn ...
- 【Mysql】数据库事务,脏读、幻读、不可重复读
一.什么是数据库事务 数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位.事务由事务开始与事务结束之间 ...
- Mysql事务,并发问题,锁机制-- 幻读、不可重复读(转)
1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...
- Mysql事务,并发问题,锁机制-- 幻读、不可重复读--专题
1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...
- 【面试普通人VS高手系列】innoDB如何解决幻读
前天有个去快手面试的小伙伴私信我,他遇到了这样一个问题: "InnoDB如何解决幻读"? 这个问题确实不是很好回答,在实际应用中,很多同学几乎都不关注数据库的事务隔离性. 所有问题 ...
- InnoDB在MySQL默认隔离级别下解决幻读
1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...
- MySQL的可重复读级别能解决幻读吗
引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了.但是对于幻 ...
- MySQL的可重复读级别能解决幻读问题吗?
之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于幻读, ...
- 面试官:MySQL的可重复读级别能解决幻读问题吗?
引言 之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于 ...
- 【Java面试】这应该是面试官最想听到的回答,Mysql如何解决幻读问题?
"Mysql如何解决幻读问题" 一个工作了4年小伙伴,去一个美团面试,遇到了这样一个问题. 大家好,我是Mic,一个工作了14年的Java程序员 关于这个问题,面试官想考察什么?我 ...
随机推荐
- CTF-Web-PHP反序列化
概念解释 PHP 反序列化漏洞又叫做 PHP 对象注入漏洞,我觉得这个表达很不直白,也不能说明根本的问题,不如我们叫他 PHP 对象的属性篡改漏洞好了(别说这是我说的~~) 反序列化漏洞的成因在于代码 ...
- 企业什么喜欢做电视看板,电视看板浏览网页的必备工具 电视看板浏览器 电视看板自动打开网页 电视看板必备APP
企业喜欢做电视看板主要是因为它可以提供以下几个方面的优势: 增强企业形象:电视看板可以将企业的信息和广告以更加生动.直观的方式呈现出来,提高企业形象和知名度. 提高工作效率:电视看板可以在企业内部作为 ...
- [Java]排序算法>选择排序>【简单选择排序】(O(n*n)/不稳定/)
1 选择排序 1.1 算法思想 每一趟从待排序的记录中选出关键字最小的记录,按顺序放在已排序的记录序列的最后(or最前面),直到全部排完位置. 1.2 算法特征 属于[选择排序] 简单选择排序 堆排序 ...
- 带你揭开神秘的javascript AST面纱之AST 基础与功能
作者:京东科技 周明亮 AST 基础与功能 在前端里面有一个很重要的概念,也是最原子化的内容,就是 AST ,几乎所有的框架,都是基于 AST 进行改造运行,比如:React / Vue /Taro ...
- Rust中的迭代器的使用:map转换、filter过滤、fold聚合、chain链接
什么是迭代器 Rust中的迭代器是一种强大的工具,它提供了一种灵活.通用的方法来遍历序列.迭代器是实现了Iterator trait的类型,并需要至少实现一个next函数,用于让迭代器指向下一个迭代对 ...
- c/c++快乐算法第三天
c/c++感受算法快乐(3) 开始时间2023-04-16 22:21:10 结束时间2023-04-17 00:09:34 前言:很好,这周就要结束了,大家都回学校了么,嘻嘻.回顾一下昨天的算法题, ...
- js如何引入高德地图API?
准备 成为开发者并创建 key 1.登录控制台 登录 高德开放平台控制台,如果没有开发者账号,请 注册开发者. 2.创建 key 进入应用管理,创建新应用,新应用中添加 key,服务平台选择 Web端 ...
- react18中antd的Upload组件上传头像,并且拿到服务器返回的头像的url地址在页面中显示头像
业务需求:上传头像,上传完毕后拿到头像的url,把头像展示在页面中,最终把头像url和其他用户信息一起发送给服务器 上传头像流程 导入 Upload 组件和图标(一个加号,一个加载中) import ...
- R-SVM-plot踩坑记录
并非所有的 svm 类型都支持plot.svm- 只有分类方法支持,而回归不支持. 所以代码应该svm_fit <- svm(factor(y)~x1+x2,data = df, kernel ...
- Android JetPack~LiveData(二) 数据倒灌问题
Android数据绑定技术一,企业级开发 Android数据绑定技术二,企业级开发 Android JetPack~ DataBinding(数据绑定)(一) 集成与使用 Android J ...