大家好,我是小林。

我之前写过一篇数据库事务的文章「 事务、事务隔离级别和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的幻读是怎么被解决的?的更多相关文章

  1. 搞定面试官 - MySQL 中你知道如何计算一个索引的长度嘛?

    大家好,我是程序员啊粥. 今天给大家分享一个我遇到过的比较少见的面试题,那就是 MySQL 中如何计算一个索引的长度. 说实话,我第一次遇到这个问题的时候想当然的以为索引长度就是我们建表时定义的字段长 ...

  2. 面试官:MySQL的可重复读级别能解决幻读问题吗?

    引言 之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于 ...

  3. MySQL 三万字精华总结 + 面试100 问,吊打面试官绰绰有余(收藏系列)

    写在之前:不建议那种上来就是各种面试题罗列,然后背书式的去记忆,对技术的提升帮助很小,对正经面试也没什么帮助,有点东西的面试官深挖下就懵逼了. 个人建议把面试题看作是费曼学习法中的回顾.简化的环节,准 ...

  4. MySQL的可重复读级别能解决幻读吗

    引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了.但是对于幻 ...

  5. Mysql加锁过程详解(2)-关于mysql 幻读理解

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  6. MySQL的可重复读级别能解决幻读问题吗?

    之前在深入了解数据库理论的时候,了解到事务的不同隔离级别可能存在的问题.为了更好的理解所以在MySQL数据库中测试复现这些问题.关于脏读和不可重复读在相应的隔离级别下都很容易的复现了. 但是对于幻读, ...

  7. MySQL到底有没有解决幻读问题?这篇文章彻底给你解答

    MySQL InnoDB引擎在Repeatable Read(可重复读)隔离级别下,到底有没有解决幻读的问题? 网上众说纷纭,有的说解决了,有的说没解决,甚至有些大v的意见都无法达成统一. 今天就深入 ...

  8. InnoDB在MySQL默认隔离级别下解决幻读

    1.结论 在RR的隔离级别下,Innodb使用MVVC和next-key locks解决幻读,MVVC解决的是普通读(快照读)的幻读,next-key locks解决的是当前读情况下的幻读. 2.幻读 ...

  9. 幻读在 InnoDB 中是被如何解决的?

    在MySQL事务初识中,我们了解到不同的事务隔离级别会引发不同的问题,如在 RR 级别下会出现幻读.但如果将存储引擎选为 InnoDB ,在 RR 级别下,幻读的问题就会被解决.在这篇文章中,会先介绍 ...

随机推荐

  1. Guava Cache 原理分析与最佳实践

    前言 目前大部分互联网架构 Cache 已经成为了必可不少的一环.常用的方案有大家熟知的 NoSQL 数据库(Redis.Memcached),也有大量的进程内缓存比如 EhCache .Guava ...

  2. 使用Cobertura做代码覆盖率测试

    经验总结:首先要把cobertura.jar包含ant的classpath路径中,其次要求它包含在测试用例的classpath中: 使用cobertura做代码覆盖率测试中出现的问题:覆盖率始终为0, ...

  3. Sqli-Labs less25-25a

    less-25 前置基础知识:后面的关卡涉及到WAF绕过: 主要有三种方式:白盒绕过.黑盒绕过.fuzz测试 网上sql注入WAF绕过的教程有很多,可以自己查询,总之就是比谁思路猥琐 根据第25关下面 ...

  4. bluecms安装错误一记

    菜鸡兴致勃勃下载了bluecms1.6准备大干一番 环境 phpstudy mysql 5.7.26 apache 2.4.39 php 7.3.4 结果安装第四步发现个这个问题   开始还以为自己这 ...

  5. SpringCloud升级之路2020.0.x版-20. 启动一个 Eureka Server 集群

    本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们的业务集群结构 ...

  6. 转载自-阮一峰-测试框架 Mocha 实例教程

    测试框架 Mocha 实例教程   作者: 阮一峰 日期: 2015年12月 3日 Mocha(发音"摩卡")诞生于2011年,是现在最流行的JavaScript测试框架之一,在浏 ...

  7. sentinel使用(结合OpenFeign)

    前提 需要先安装sentinel. 父项目POM pom.xml <?xml version="1.0" encoding="UTF-8"?> &l ...

  8. mysql删除大表更快的办法

    实现:巧用LINK(硬链接),原理:linux文件系统中硬链接相当于文件的入口,记录着ionde的信息.一个文件存在多个硬连接时,删除一个硬链接不会真正的删除ionde(存储文件的数据) # 创建硬链 ...

  9. C#中,async关键字到底起什么作用?

    标记了async,函数里就可以用await,return的语义也会发生变化,返回类型也必须是Task或者Task<T>.所以这就是个语法而已,不要去对async钻牛角尖.你这个问题就像为什 ...

  10. mysql几种连接方式区别

    mysql的几种join 2017年03月19日 14:49:07 carl-zhao 阅读数:7845 标签: mysqlsqljoin 更多 个人分类: MySQL 版权声明:本文为博主原创文章, ...