解决Mysql中的innoDB幻读问题


Posted in MySQL onApril 29, 2022

1.Mysql的事务隔离级别

解决Mysql中的innoDB幻读问题

这四种隔离级别,当存在多个事务并发冲突的时候,可能会出现脏读,不可重复读,幻读的一些问题,而innoDB在可重复读隔离级别模式下解决了幻读的一个问题,

2. 什么是幻读

幻读是指在同一个事务中,前后两次查询相同范围的时候得到的结果不一致

解决Mysql中的innoDB幻读问题

如图,第一个事务里面,我们执行一个范围查询,这个时候满足条件的数据只有一条,而在第二个事务里面,它插入一行数据并且进行了提交,接着第一个事务再去查询的时候,得到的结果比第一次查询的结果多出来一条数据,注意第一个事务的第一次和第二次查询,都在同一个事物里面,所以,幻读会带来数据一致性的问题

3. InnoDB如何解决幻读的问题

InnoDB引入间隙锁next-key lock机制去解决幻读问题

解决Mysql中的innoDB幻读问题

假如现在存在这样一个B+Tree的索引结构,这个结构有4个索引元素,分别是1,4,7,10 当我们通过主键索引查询一条记录,并且对这条记录通过for update加锁的时候

解决Mysql中的innoDB幻读问题

这个时候会产生一个记录锁,也就是行锁,锁定id=1这个索引

解决Mysql中的innoDB幻读问题

被锁定的记录在锁释放之前,其他事务无法对这一条记录做任何操作的,前面我们所过对幻读的定义,幻读是指在同一个事务中,前后两次查询相同范围的时候得到的结果不一致,注意这里敲掉的是范围查询,也就是说要解决幻读的问题,必须保证一个点

解决Mysql中的innoDB幻读问题

就是如果一个事务通过这样一条语句进行锁定的时候,另外一个事务再执行

解决Mysql中的innoDB幻读问题

这样一条insert语句需要被阻塞,直到前面获得所的事务被释放,所以在innonDB设计一种间隙锁,它的主要功能是锁定一定范围内的索引记录

解决Mysql中的innoDB幻读问题

当对查询范围id > 4 and id < 7这个范围加锁的时候,会针对B+数中(4,7)这个开区间的范围加间隙锁,意味着在这种情况下其他事务对这个区间的数据进行插入更新删除都会被锁住,但是还有另外一种情况,比如像这样

解决Mysql中的innoDB幻读问题

这条查询语句针对id > 4这个条件加锁,那么它需要锁定多个索引区间,所以这个情况下InnoDB引入一个叫next-key lock机制,next-key lock相当于间隙锁和记录锁的合集,记录锁锁定存在记录的行,间隙锁锁住的是记录行之间的间隙,而next-key lock锁住的是两者的和

解决Mysql中的innoDB幻读问题

每个数据行非唯一的索引列,都会存在一把next-key lock,当某个事务持有这一行数据的next-key lock的时候,会锁住一段在左开右闭区间的数据,因此当通过id > 4这样一个范围加锁的时候,InnoDB会去加一个next-key lock锁,锁定的区间范围是(4,7 ](7,10 ](10,+♾️ ]。间隙锁next-key lock的区别是在加锁的范围,间隙锁锁定的是两个索引之间的间隙,而next-key lock会锁定多个索引区间,它包含记录锁间隙锁当我们使用范围查询不仅仅命中Record记录,还包含了Gap间隙的时候,在这种情况下使用的就是临键锁,也就是next-key lock它是Mysql里面默认的行锁算法

4. 总结

虽然InnoDB里面通过间隙锁方式解决了幻读的问题但是加锁之后一定会影响到并发性能,因此对与性能较高的一些业务场景,我们可以把隔离级别设置不可重复,那么这个级别不存在间隙锁,也不存在性能的影响。


Tags in this post...

MySQL 相关文章推荐
MySQL pt-slave-restart工具的使用简介
Apr 07 MySQL
MySQL创建索引需要了解的
Apr 08 MySQL
解决mysql问题:由于找不到MSVCR120.dll,无法继续执行代码
Jun 26 MySQL
mysql left join快速转inner join的过程
Jun 30 MySQL
mysql连接查询中and与where的区别浅析
Jul 01 MySQL
MySQL数据库索引的最左匹配原则
Nov 20 MySQL
一条 SQL 语句执行过程
Mar 17 MySQL
一文简单了解MySQL前缀索引
Apr 03 MySQL
Mysql 8.x 创建用户以及授予权限的操作记录
Apr 18 MySQL
MySQL 语句执行顺序举例解析
Jun 05 MySQL
MySQL数据库之存储过程 procedure
Jun 16 MySQL
Mysql表数据比较大情况下修改添加字段的方法实例
Jun 28 MySQL
详解Mysq MVCC多版本的并发控制
详解Mysql事务并发(脏读、不可重复读、幻读)
MySQL 条件查询的常用操作
Apr 28 #MySQL
mysql 子查询的使用
Apr 28 #MySQL
Mysql 数据库中的 redo log 和 binlog 写入策略
Apr 26 #MySQL
优化Mysql查询的示例
Apr 26 #MySQL
MySQL的存储过程和相关函数
Apr 26 #MySQL
You might like
php身份证号码检查类实例
2015/06/18 PHP
PHP结合Mysql数据库实现留言板功能
2016/03/04 PHP
thinkPHP5.0框架URL访问方法详解
2017/03/18 PHP
php反序列化长度变化尾部字符串逃逸(0CTF-2016-piapiapia)
2020/02/15 PHP
整理Javascript基础入门学习笔记
2015/11/29 Javascript
jQuery+PHP实现微信转盘抽奖功能的方法
2016/05/25 Javascript
使用JS正则表达式 替换括号,尖括号等
2016/11/29 Javascript
jQuery使用siblings获取某元素所有同辈(兄弟姐妹)元素用法示例
2017/01/30 Javascript
Angular2数据绑定详解
2017/04/18 Javascript
JS判断字符串是否为整数的方法--简单的正则判断
2018/07/23 Javascript
在React项目中使用Eslint代码检查工具及常见问题
2018/10/10 Javascript
详解在微信小程序的JS脚本中使用Promise来优化函数处理
2019/03/06 Javascript
WebGL学习教程之Three.js学习笔记(第一篇)
2019/04/25 Javascript
python求列表交集的方法汇总
2014/11/10 Python
完美解决Python2操作中文名文件乱码的问题
2017/01/04 Python
Python subprocess模块常见用法分析
2018/06/12 Python
Python格式化输出字符串方法小结【%与format】
2018/10/29 Python
python 判断文件还是文件夹的简单实例
2019/06/10 Python
python flask框架实现传数据到js的方法分析
2019/06/11 Python
Pytorch 实现focal_loss 多类别和二分类示例
2020/01/14 Python
python求前n个阶乘的和实例
2020/04/02 Python
Pytorch转keras的有效方法,以FlowNet为例讲解
2020/05/26 Python
python文件及目录操作代码汇总
2020/07/08 Python
Python  word实现读取及导出代码解析
2020/07/09 Python
Pytorch 图像变换函数集合小结
2021/02/01 Python
美国折扣网站:jClub
2017/08/07 全球购物
孤独星球出版物:Lonely Planet Publications
2018/03/17 全球购物
巴西一家专门从事家居和装饰的连锁店:Camicado
2019/08/14 全球购物
俄罗斯游戏商店:Buka
2020/03/01 全球购物
Bloomingdale’s阿联酋:选购奢华时尚、美容及更多
2020/09/22 全球购物
归元寺导游词
2015/02/06 职场文书
2015年七一建党节活动总结
2015/03/20 职场文书
2016年班主任培训心得体会
2016/01/07 职场文书
配置nginx 重定向到系统维护页面
2021/06/08 Servers
教你如何使用Python实现二叉树结构及三种遍历
2021/06/18 Python
搞笑Gif:这么白这么长的腿像极了一楼的女朋友
2022/03/21 杂记