一次性掌握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程序员 关于这个问题,面试官想考察什么?我 ...
随机推荐
- 两条命令搞定 ChatGPT API 的调用问题
自2022年11月30日 OpenAI 发布 ChatGPT 以来,虽然时有唱衰的声音出现,但在OpenAI不断推陈出新,陆续发布了OpenAPI.GPT-4.ChatGPT Plugins之后,似乎 ...
- 一文总结你需要的OpenCV操作
目录 一.OpenCV简介 1.1 OpenCV是什么 1.2 安装及使用 二.图像的基础 2.1 成像原理 2.2 图像格式 2.3 颜色空间 三.OpenCV基础操作 3.1 图像的读取.显示.保 ...
- 3d基础 - 从模型坐标到屏幕坐标
在 3D 引擎中,场景通常被描述为三维空间中的模型或对象,每个模型对象由许多三维顶点组成.最终,这些模型对象将在平面屏幕上呈现和显示. 渲染场景始终相对于摄像机,因此,还必须相对于摄像机的视图定义场景 ...
- 学习docker看此文足以
什么是 Docker Docker 最初是 dotCloud 公司创始人 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 ,主要项目代码在 上进行 ...
- mysql迁移:docker迁入迁出mysql
docker迁出mysql数据库 测试环境: docker服务器 mysql服务器 IP 192.168.163.19 192.168.163.16 操作系统 CentOS7.8 CentOS7.8 ...
- 【Java SE】枚举类和注解
1.枚举类的使用 当类的对象由有限个,确定的时候,我们称这种类为枚举类.当需要定义一组常量时,建议使用枚举类.而当枚举类中只有一个对象时,可以使用单例模式. 1.1 enmu关键字 省略private ...
- LeetCode 周赛 340,质数 / 前缀和 / 极大化最小值 / 最短路 / 平衡二叉树
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 上周跟大家讲到小彭文章风格的问题,和一些朋友聊过以后,至少在算法题解方面确定了小彭的风格 ...
- Matlab蚁群算法求解旅行商问题
目录 问题展现 解决代码 代码1 输出结果 代码2 输出结果 代码3 输出结果 问题展现 假设有一个旅行商人要拜访全国 31 个省会城市,他需要选择所要走的路径,路径的限制是每个城市只能拜访一次,而且 ...
- DRF版本控制(源码分析)
DRF中版本控制的五种情况(源码分析) 在restful规范中要去,后端的API中需要体现版本. drf框架中支持5种版本的设置. 1. URL的GET参数传递(*) 示例: user/?versio ...
- 使用Vue.js实现文字跑马灯效果
实现文字跑马灯效果,首先用到 substring()截取 和 setInterval计时器 clearInterval()清除计时器 效果如下: 实现代码如下: <!DOCTYPE html&g ...