面试官:MySQL的幻读是怎么被解决的?
大家好,我是小林。
我之前写过一篇数据库事务的文章「 事务、事务隔离级别和MVCC」,这篇我说过什么是幻读。
在这里插入图片描述
然后前几天有位读者跟我说,我这个幻读例子不是已经被「可重复读」隔离级别解决了吗?为什么还要有 next-key 呢?
他有这个质疑,是因为他做了这个实验。
实验的数据库表 t_stu 如下,其中 id 为主键。
在这里插入图片描述
然后在可重复读隔离级别下,有两个事务的执行顺序如下:
在这里插入图片描述
从这个实验结果可以看到,即使事务 B 中途插入了一条记录,事务 A 前后两次查询的结果集都是一样的,并没有出现所谓的幻读现象。
读者做的实验之所以看不到幻读现象,是因为在可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入的数据的。
可重复读隔离级是由 MVCC(多版本并发控制)实现的,实现的方式是启动事务后,在执行第一个查询语句后,会创建一个视图,然后后续的查询语句都用这个视图,「快照读」读的就是这个视图的数据,视图你可以理解为版本数据,这样就使得每次查询的数据都是一样的。
MySQL 里除了普通查询是快照度,其他都是当前读,比如update、insert、delete,这些语句执行前都会查询最新版本的数据,然后再做进一步的操作。
这很好理解,假设你要 update 一个记录,另一个事务已经 delete 这条记录并且 提交事务了,这样不是会产生冲突吗,所以 update 的时候肯定要知道最新的数据。
另外,select ... for update 这种查询语句是当前读,每次执行的时候都是读取最新的数据。
因此,要讨论「可重复读」隔离级别的幻读现象,是要建立在「当前读」的情况下。
接下来,我们假设select ... for update当前读是不会加锁的(实际上是会加锁的),在做一遍读者那个实验。

这时候,事务 B 插入的记录,就会被事务 A 的第二条查询语句查询到(因为是当前读),这样就会出现前后两次查询的结果集合不一样,这就出现了幻读。
所以,Innodb 引擎为了解决「可重复读」隔离级别使用「当前读」而造成的幻读问题,就引出了 next-key 锁,就是记录锁和间隙锁的组合。
- 记录锁,锁的是记录本身;
- 间隙锁,锁的就是两个值之间的空隙,以防止其他事务在这个空隙间插入新的数据,从而避免幻读现象。
比如,执行这条语句的时候,会锁住,然后期间如果有其他事务在这个锁住的范围插入数据就会被阻塞。

next-key 锁的加锁规则其实挺复杂的,在一些场景下会退化成记录锁或间隙锁,我之前也写一篇加锁规则,详细可以看这篇「我做了一天的实验!」
需要注意的是,next-key lock 锁的是索引,而不是数据本身,所以如果 update 语句的 where 条件没有用到索引列,那么就会全表扫描,在一行行扫描的过程中,不仅给行加上了行锁,还给行两边的空隙也加上了间隙锁,相当于锁住整个表,然后直到事务结束才会释放锁。
所以在线上千万不要执行没有带索引的 update 语句,不然会造成业务停滞,我有个读者就因为干了这个事情,然后被老板教育了一波,详细可以看这篇「完蛋,公司被一条 update 语句干趴了!」
好了,这次就聊到这啦,学到的点个赞呀!
面试官:MySQL的幻读是怎么被解决的?的更多相关文章
- 搞定面试官 - MySQL 中你知道如何计算一个索引的长度嘛?
大家好,我是程序员啊粥. 今天给大家分享一个我遇到过的比较少见的面试题,那就是 MySQL 中如何计算一个索引的长度. 说实话,我第一次遇到这个问题的时候想当然的以为索引长度就是我们建表时定义的字段长 ...
- 面试官:MySQL的可重复读级别能解决幻读问题吗?
引言 之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于 ...
- MySQL 三万字精华总结 + 面试100 问,吊打面试官绰绰有余(收藏系列)
写在之前:不建议那种上来就是各种面试题罗列,然后背书式的去记忆,对技术的提升帮助很小,对正经面试也没什么帮助,有点东西的面试官深挖下就懵逼了. 个人建议把面试题看作是费曼学习法中的回顾.简化的环节,准 ...
- MySQL的可重复读级别能解决幻读吗
引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了.但是对于幻 ...
- Mysql加锁过程详解(2)-关于mysql 幻读理解
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- MySQL的可重复读级别能解决幻读问题吗?
之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于幻读, ...
- MySQL到底有没有解决幻读问题?这篇文章彻底给你解答
MySQL InnoDB引擎在Repeatable Read(可重复读)隔离级别下,到底有没有解决幻读的问题? 网上众说纷纭,有的说解决了,有的说没解决,甚至有些大v的意见都无法达成统一. 今天就深入 ...
- InnoDB在MySQL默认隔离级别下解决幻读
1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...
- 幻读在 InnoDB 中是被如何解决的?
在MySQL事务初识中,我们了解到不同的事务隔离级别会引发不同的问题,如在 RR 级别下会出现幻读.但如果将存储引擎选为 InnoDB ,在 RR 级别下,幻读的问题就会被解决.在这篇文章中,会先介绍 ...
随机推荐
- 响应式编程基础教程:Spring Boot 与 Lettuce 整合
本文主要介绍响应式编程访问 Redis,以及 Spring Boot 与 Lettuce 的整合使用. Lettuce 是可扩展性线程安全的 Redis 客户端,用于同步.异步和响应式使用.如果多个线 ...
- SpringMVC项目部署到CentOS7虚拟机问题及解决办法记录
1.前言 计划将之前在Windows系统上练手做的项目部署到云服务器上,想先在本地虚拟机上测试一下是否可行,过程中发现很多问题,特此记录.还有问题未能解决,希望后面能有思路. 突然想到是否和数据库有关 ...
- SQL injection : UNION attacks
当应用程序易受SQL注入攻击并且查询结果在应用程序的响应中返回时,可以使用UNION关键字从数据库中的其他表检索数据.这将导致SQL注入联合攻击. UNION关键字允许您执行一个或多个附加的SELEC ...
- 简略图解:输入 url 到出现页面,浏览器做了什么?
应该有很多前端开发人员都思考过这么一个问题:从输入 URL 到页面加载完成,中间都做发生了什么? 这个问题涉及的面非常广,每个涉及的点又很深入.从触屏/键盘如何到 CPU?CPU 如何到系统内核?如何 ...
- KVM常用命令
查看所有虚拟机状态:执行virsh list –all 启动该虚拟机:执行virsh start test 关机虚拟机:virsh shutdown 此方法为正常关机方法,需要一段才能关机关闭 ...
- SQL 练习28
查询平均成绩大于等于 85 的所有学生的学号.姓名和平均成绩 SELECT Student.SId,Student.Sname,平均成绩 FROM Student , (SELECT sid,AVG( ...
- sentinel使用(结合gateway)
前 如果你想在Spring Cloud Gateway中使用Sentinel Starter,你需要添加Spring - Cloud -alibaba- Sentinel - Gateway依赖,并添 ...
- leaflet 的 marker 弹框 iframe 嵌套代码
A页面 嵌套 B页面的代码 主要处理 leaflet 的 marker 的 popopen, marker的点击的显示/隐藏 pop 会导致pop中的页面的内容,消失,不在页面中,导致b ...
- C#中Finalize方法的问题
ninputer在关于"值类型的Finalize不会被调用"中(http://blog.joycode.com/lijianzhong/archive/2005/01/13/429 ...
- ArcGIS地形分析--TIN及DEM的生成,TIN的显示
DEM是对地形地貌的一种离散的数字表达,是对地面特性进行空间描述的一种数字方法.途径,它的应用可遍及整个地学领域.通过对本次实习的学习,我们应加深对TIN建立过程的原理.方法的认识:熟练掌握ArcGI ...