幻读是 MySQL 中一个非常普遍,且面试中经常被问到的问题,如果你还搞不懂什么是幻读?什么是 MVCC?以及 MySQL 中的锁?那么请好好收藏和阅读本篇文章,因为它非常重要。

RR 隔离级别

在 MySQL 中,RR 代表 Repeatable Read(可重复读),是数据库事务隔离级别中的一种,它的特性是保证同一个事务中,多次读取同一条记录时,读取到的数据都是一致的。它也是 MySQL 默认的事务隔离级别。

隔离级别是数据库管理系统为了处理并发访问时,控制事务之间相互影响的程度而定义的一组规则。

MVCC

MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种并发控制机制,用于在数据库系统中处理并发读写操作时保持数据的一致性和隔离性(主要是用来解决幻读问题的)。MVCC 通过在每个数据行上保存多个版本的数据来实现并发读取和写入的一致性。

MVCC 的核心思想是将每个事务的读操作与写操作解耦,通过保存数据的历史版本来实现并发控制。每个事务在开始时会创建一个读视图(Read View),用于确定在事务开始时可见的数据版本。读视图包含一个事务开始时的系统版本号,用于与数据行的版本号进行比较,以确定数据行是否对事务可见。

在 MVCC 中,当一个事务执行写操作时,会生成一个新的数据版本,并将旧版本的数据保存在回滚日志(Undo Log)中。这样,其他事务在读取数据时仍然可以访问到旧版本的数据,从而避免了幻读问题。

MVCC 工作流程如下:

  1. 读操作:当一个事务执行 SELECT 语句时,会根据读视图的系统版本号和数据行的版本号进行比较,只读取在事务开始之前已经提交的数据行。这样,即使其他事务正在并发地插入或删除数据,事务仍然可以读取到一致的数据。
  2. 写操作:当一个事务执行 INSERT、UPDATE 或 DELETE 语句时,会生成新的数据版本,并将旧版本的数据保存在回滚日志中。这样,其他事务在读取数据时仍然可以访问到旧版本的数据,从而避免了幻读问题。

MVCC 机制在数据库系统中广泛应用,特别是在支持事务的存储引擎中,如 MySQL 的 InnoDB 引擎。它通过解耦读操作和写操作,提供了高并发性能和数据一致性,使得多个事务可以同时读取和修改数据库,而不会相互干扰。

RR + MVCC 有幻读问题吗?

在 MySQL 中,即使是RR 隔离级别(可重复读),虽然它通过 MVCC 消除了绝大部分幻读问题,但依旧存在部分幻读问题,所以 RR 隔离级别存在幻读问题,而 MVCC 也没有彻底解决幻读问题。

幻读问题演示

在 RR 隔离级别中存在两种读操作:

  1. 快照读:数据库中一种读取数据的方式,它基于事务开始时的一个一致性快照来读取数据。快照读可以提供事务开始时的数据视图,即使在事务执行期间其他事务对数据进行了修改,也不会影响快照读取到的数据。简单理解,快照读就是事务开启时创建一个缓存,之后的查询都会从这个缓存中获取数据。
  2. 当前读:数据库中一种读取数据的方式,它读取最新提交的数据,而不是基于事务开始时的一致性快照。

所以,在 RR 隔离级别中 MVCC 通过快照读的方式解决了大部分幻读问题,但如果 RR 隔离级别存在当前读(使用 select ... for update 实现),那么此时也会发生幻读问题,比如以下执行过程:

如何彻底解决幻读?

想要彻底解决幻读问题,有两个方案:

  1. 使用串行化(Serializable)隔离级别:官方推荐方案,但这种解决方案,并发性能比较低。
  2. RR + 锁:使用 RR 隔离级别,但在事务开启之后立即加锁,如下图所示:事务一开启之后就加锁,之后其他事务在操作此表的相关数据时,就只能等待锁释放(事务一提交或回滚锁自动释放)。

小结

在可重复读级别中,MySQL 虽然使用 MVCC 解决了大部分幻读问题,但在当前读的操作中依然有幻读问题,此时可以通过加锁,或升级隔离级别为串行化来解决幻读问题。

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

RR有幻读问题吗?MVCC能否解决幻读?的更多相关文章

  1. MVCC 能解决幻读吗?

    MySQL通过MVCC(解决读写并发问题)和间隙锁(解决写写并发问题)来解决幻读 MySQL InnoDB事务的隔离级别有四级,默认是“可重复读”(REPEATABLE READ). 未提交读(REA ...

  2. MySQL锁(三)行锁:幻读是什么?如何解决幻读?

    概述 前面两篇文章介绍了MySQL的全局锁和表级锁,今天就介绍一下MySQL的行锁. MySQL的行锁是各个引擎内部实现的,不是所有的引擎支持行锁,例如MyISAM就不支持行锁. 不支持行锁就意味着在 ...

  3. MySQL 是如何解决幻读的

    MySQL 是如何解决幻读的 一.什么是幻读 在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读. 而多出来或者少的哪一行被叫做 幻行 二.为什么要解决幻读 在高并发数据库系统中,需要保证 ...

  4. 何为幻读?MySQL又是如何解决幻读的?

    一.什么是幻读 在一次事务里面,多次查询之后,查询的结果集的个数不一致的情况叫做幻读.而多出来或者少的哪一行被叫做 幻行 二.为什么要解决幻读 在高并发数据库系统中,需要保证事务与事务之间的隔离性,还 ...

  5. 【大厂面试03期】MySQL是怎么解决幻读问题的?

    问题分析 首先幻读是什么? 根据MySQL文档上面的定义 The so-called phantom problem occurs within a transaction when the same ...

  6. MySQL到底能否解决幻读问题

    先说结论,MySQL 存储引擎 InnoDB 在可重复读(RR)隔离级别下是解决了幻读问题的. 方法:是通过next-key lock在当前读事务开启时,1.给涉及到的行加写锁(行锁)防止写操作:2. ...

  7. InnoDB 是如何解决幻读的

    前言 大部分人在日常的业务开发中,其实很少去关注数据库的事务相关问题,基本上都是 CURD 一把梭.正好最近在看 MySQL 的相关基础知识,其中对于幻读问题之前一直没有理解深刻,今天就来聊聊「Inn ...

  8. InnoDB解决幻读的方案——LBCC&MVCC

    最近要在公司内做一次技术分享,思来想去不知道该分享些什么,最后在朋友的提示下,准备分享一下MySQL的InnoDB引擎下的事务幻读问题与解决方案--LBCC&MVCC.经过好几天的熬夜通宵,终 ...

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

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

  10. MySQL 到底是怎么解决幻读的?

    ; 原理:将历史数据存一份快照,所以其他事务增加与删除数据,对于当前事务来说是不可见的. 2. next-key 锁 (当前读) next-key 锁包含两部分: 记录锁(行锁) 间隙锁 记录锁是加在 ...

随机推荐

  1. Webpack5构建性能优化:构建耗时从150s到60s再到10s

    作者:京东科技 牛志伟 近期对Webpack5构建性能进行了优化,构建耗时从150s到60s再到10s,下面详细讲解下优化过程. 优化前现状 1.历史项目基于Vue3 + Webpack5技术栈,其中 ...

  2. 用tk.mybaits实现指定字段更新

    ​ 去年年底的因为业务需要需要在使用tk.mybaits框架的系统中实现指定字段的更新,可是tk.mybaits框架本身并不支持这个功能,我翻遍了CSDN和其他相关的技术相关的网站都没有找到相关的解决 ...

  3. 2022-07-21:给定一个字符串str,和一个正数k, 你可以随意的划分str成多个子串, 目的是找到在某一种划分方案中,有尽可能多的回文子串,长度>=k,并且没有重合。 返回有几个回文子串。 来

    2022-07-21:给定一个字符串str,和一个正数k, 你可以随意的划分str成多个子串, 目的是找到在某一种划分方案中,有尽可能多的回文子串,长度>=k,并且没有重合. 返回有几个回文子串 ...

  4. 2022-06-30:以下golang代码输出什么?A:0;B:2;C:运行错误。 package main import “fmt“ func main() { ints := make

    2022-06-30:以下golang代码输出什么?A:0:B:2:C:运行错误. package main import "fmt" func main() { ints := ...

  5. 2022-04-26:给定四个整数 sx , sy ,tx 和 ty,如果通过一系列的转换可以从起点 (sx, sy) 到达终点 (tx, ty),则返回 true,否则返回 false。 从点 (x

    2022-04-26:给定四个整数 sx , sy ,tx 和 ty,如果通过一系列的转换可以从起点 (sx, sy) 到达终点 (tx, ty),则返回 true,否则返回 false. 从点 (x ...

  6. Django4全栈进阶之路9 STATIC静态文件路径设置、MEDIA媒体文件路径设置

    在 Django 4 中,可以在 settings.py 文件中设置 STATICFILES_DIRS 来指定应用程序静态文件所在的文件夹路径,设置 STATIC_ROOT 来指定收集所有应用程序静态 ...

  7. Charles抓包补充解释

    配置 大佬的博客真的很详细很详细,我就不重复造轮子了,第一次直接看大佬的博客就好,这里Python爬取微信小程序(Charles) 补充解释 在这一步疑问很多,大佬说的不是很详细,就由我来补充下吧~ ...

  8. Vue cli3 整合SuperMap巧遇js异步加载的坑

    最近使用到superMap做三维地图,而项目又分为可视化大屏与后台管理系统两部分,所以项目配置了多入口,然引入cesium依赖就成了问题,在vue cli3 整合Cesium,处理build 时内存溢 ...

  9. CSS3 clip-path:打造独特创意设计效果的秘密武器

    大家好,我是程序视点的小二哥. 今天小二哥将给大家分享一篇有前端实验室的文章.一部由CSS技术实现的作品.它将再一次证明CSS的强大力量. 欣赏 这是一部由阿姆斯特丹设计师Bryan James通过3 ...

  10. 一篇文章带你入门HBase

    本文已收录至Github,推荐阅读 Java随想录 微信公众号:Java随想录 目录 HBase特性 Hadoop的限制 基本概念 NameSpace Table RowKey Column Time ...