MVCC 和间隙锁是两种完全不同的机制,但它们的目的都是相同的,都是用来保证数据库并发访问的,我们先来看二者的定义。

MVCC 定义

MVCC 是多版本并发控制(Multi-Version Concurrency Control)的缩写,是一种并发控制的方法。

在 MVCC 中,每个读操作会看到一个固定版本的数据库记录,即使在并发环境中,也不会出现读取到了其他事务还未提交的数据的情况。

MVCC 通过保存数据在某个时间点的快照来实现这一点。在读取数据时,只会读取在该时间点之前提交的数据。在写入数据时,会为每个写入操作创建一个新版本的数据,而不是直接覆盖原有的数据。这样,读操作就可以读取旧版本的数据,而写操作则可以写入新版本的数据,从而实现了并发控制。

在 MySQL 中,InnoDB 存储引擎就是使用 MVCC 来实现并发控制的。

间隙锁定义

间隙锁是一种锁定索引范围而非实际数据的锁,它可以锁定一个范围,防止其他事务在这个范围内插入数据,从而保证了范围内的数据的唯一性。在 MySQL 中,InnoDB 存储引擎支持间隙锁。当使用 SELECT ... FOR UPDATE 或 SELECT ... LOCK IN SHARE MODE 语句时,InnoDB 存储引擎会自动使用间隙锁来锁定索引范围。

如果一个事务在一个间隙上持有了锁,那么其他事务就不能在这个间隙上插入数据,但是可以在这个间隙之前或之后的位置插入数据。

为什么要有 MVCC?

既然已经有锁可以防止并发访问了,那为什么还需要 MVCC 呢?

MVCC 的诞生主要是出于性能的考虑,因为 MVCC 中没有用到锁,它是通过多版本并发控制的手段来实现数据库并发访问的,这样相比于加锁性能就会好很多。

MVCC 实现原理

MVCC 竟然这么强,那它是怎么实现的呢?

简单来说 MVCC 是通过以下 3 大组件实现的:

  1. 隐藏字段:每个执行的 SQL 命令都有几个隐藏的字段,其中有一个事务 ID 字段,很重要。
  2. undo log(回滚日志):里面记录了 SQL 命令执行的历史数据。
  3. Read View(读视图):包含快照读(一个快照,保存了数据库某个时刻的数据)和一些重要的属性。

它的实现原理简单来说,是通过 SQL 中隐藏的字段事务 ID(自己的版本号)和 Read View 中的属性版本号进行对比,对比之后决定使用 Read View 中的快照或 undo log 中的历史数据(对比的规则是 MVCC 机制的规定,本文不展开讨论),最后再将符合的数据返回。

MVCC 可以解决幻读吗?

幻读是指在一个事务中,第一次查询某个范围的数据时,发现有一些数据符合条件,但是当再次查询同样的范围时,却发现多了一些或者少了一些数据。这种情况就被称为幻读。幻读是由于并发事务中的数据修改操作导致的,比如在一个事务中,另一个事务插入了一条符合条件的数据,导致第二次查询时多了一条数据。

MVCC 机制可以解决部分幻读问题,MVCC 是通过保存数据在某个时间点的快照来实现来解决(部分)幻读问题的,在读取数据时,MVCC 会根据快照来确定可见的数据版本。这样,即使其他事务在读取数据时进行了修改,也不会影响当前事务的读取结果。

因此,MVCC 可以有效地解决这部分幻读问题。但需要注意的是,MVCC 只能解决读取数据时的幻读问题,对于写入数据时的幻读问题,还需要配合锁机制或使用更高的事务隔离级别(串行化)来解决。

也就是说,想要彻底解决 MySQL InnoDB 中 RR(REPEATABLE READ,可重复读)事务隔离级别的幻读问题,需要使用 MVCC + 锁机制共同来实现。

锁分类

在 MySQL InnoDB 中的锁机制不止有间隙锁,还有行锁和临建锁等。

行锁、间隙锁和临建锁有什么区别?

行锁、间隙锁和临建锁都是 MySQL 中的锁机制,它们的区别如下:

  • 行锁是针对某一行数据进行的锁定,可以防止其他事务修改该行数据。
  • 间隙锁是针对某一范围的数据进行的锁定,可以防止其他事务在该范围内插入数据。
  • 临建锁是行锁和间隙锁的组合,可以理解为一种特殊的间隙锁,它等于行锁+间隙锁,除了锁住记录本身,还会锁住索引之间的间隙,即锁定一段左开右闭的索引区间。

小结

MVCC 和锁机制解决了 MySQL InnoDB 中 RR 事务隔离级别的幻读问题,而 MySQL 中的锁类型又有很多种,如行锁、间隙锁、临建锁等。

本文已收录到 Gitee 开源仓库《Java 面试突击》,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。Java 面试有它就够了:最全 Java 面试题库(2023版),持续更新...

面试突击:MVCC 和间隙锁有什么区别?的更多相关文章

  1. mysql幻读、MVCC、间隙锁、意向锁(IX\IS)

    IO即性能 顺序主键写性能很高,由于B+树的结构,主键如果是顺序的,则磁盘页的数据会按顺序填充,减少数据移动,随机主键则可能由于记录移动产生很多io 查询二级索引时,会再根据主键id获取数据页,产生一 ...

  2. Mysql 间隙锁原理,以及Repeatable Read隔离级别下可以防止幻读原理(百度)

    Mysql知识实在太丰富了,前几天百度的面试官问我MySql在Repeatable Read下面是否会有幻读出现,我说按照事务的特性当然会有, 但是面试官却说 Mysql 在Repeatable Re ...

  3. 【Java面试】为什么引入偏向锁、轻量级锁,介绍下升级流程

    Hi,我是Mic 一个工作了7年的粉丝来找我,他说最近被各种锁搞晕了. 比如,共享锁.排它锁.偏向锁.轻量级锁.自旋锁.重量级锁. 间隙锁.临键锁.意向锁.读写锁.乐观锁.悲观锁.表锁.行锁. 然后前 ...

  4. MySQL 是怎么加行级锁的?为什么一会是 next-key 锁,一会是间隙锁,一会又是记录锁?

    大家好,我是小林. 是不是很多人都对 MySQL 加行级锁的规则搞的迷迷糊糊,一会是 next-key 锁,一会是间隙锁,一会又是记录锁. 坦白说,确实还挺复杂的,但是好在我找点了点规律,也知道如何如 ...

  5. mysql锁机制之间隙锁(Next-Key锁)(五)

    间隙锁(Next-Key锁) 当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的 索引项加锁:对于键值在条件范围内但并不存在的记录,叫做“间隙(GA ...

  6. mysql 隔离级别与间隙锁等

    数据库隔离级 SQL标准中DB隔离级别有: read uncommitted:可以读到其它transaction 未提交数据 read committed:可以读到其它transaction 已提交数 ...

  7. 《【面试突击】— Redis篇》-- Redis的线程模型了解吗?为啥单线程效率还这么高?

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis的线程模型了解吗?为啥单线程效率还这 ...

  8. 视频+图文串讲:MySQL 行锁、间隙锁、Next-Key-Lock、以及实现记录存在的话就更新,如果记录不存在的话就插入如何保证并发安全

    导读 Hi,大家好!我是白日梦!本文是MySQL专题的第 27 篇. 下文还是白日梦以自导自演的方式,围绕"如何实现记录存在的话就更新,如果记录不存在的话就插入."展开本话题.看看 ...

  9. MySQL锁(表锁,行锁,共享锁,排它锁,间隙锁)使用详解

    锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具.在计算机中,是协调多个进程或县城并发访问某一资源的一种机制.在数据库当中,除了传统的计算资源(CPU.RAM.I/O等等)的争用之外,数据也是一 ...

  10. Mysql Innodb 间隙锁浅析

    间隙锁说明 innodb引擎自动使用间隙锁来避免幻读(原因是因为innodb采用单行锁+间隙锁组合而成的行锁,会锁定一个范围和记录本身的行),参数默认innodb_locaks_unsafe_for_ ...

随机推荐

  1. K Smallest In Unsorted Array

    Find the K smallest numbers in an unsorted integer array A. The returned numbers should be in ascend ...

  2. HTTP-看这一篇就够了

    HTTP和HTTPS有什么区别 1.传输过程中信息是否加密,HTTP是超文本传输协议,信息是明文传输,HTTPS是具有安全性的SSL加密的超文本传输协议,信息是加密传输: 2.服务端使用的端口号不一致 ...

  3. Python-pytest -> 在自动化测试中,如何切换不同的测试环境

    在构建自动化测试的脚本时候,我们可能会有不同环境的测试需求,如何实现在不同的测试环境之间切换呢?接下来介绍的这种方法,可以自定义命令行参数,从而根据不同的参数值实现不同环境的切换. 解决办法: 使用h ...

  4. sourceTree工具使用方法

    https://www.cnblogs.com/tian-xie/p/6264104.html

  5. 后端返回字符流,前端处理进行excel文件导出操作

    针对于这种的文件导出,最关键的是响应类型的设置,也就是responseType的设置(responseType:"arraybuffer"或者responseType:" ...

  6. vue-固定头部-内容可滚动

     <div class="show-box">             <div class="show-top">           ...

  7. 1、HTTP的基本概念与交互模型

    1.上网的整个过程 假设我们点击了某网页上的一个链接,指向清华大学院系设置,其URL是:http://www.tsinghua.edu.cn/chn/yxsz/index.html.我们来分析一下整个 ...

  8. datax-web踩坑记录

    实习期间接触了两种ETL工具:kettle.datax 1.datax-web的安装 (跟着文档一步步来就好了) https://github.com/WeiYe-Jing/datax-web/blo ...

  9. java学习笔记(五)运算符

    ++ --   自增自减 a++ 执行完这行代码后,先给b赋值,再自增 ++a 执行完这行代码前,先自增,再给b赋值 Math类

  10. COM调用 – VB、PB

    本文使用Delphi和C++创建CRC32的COM文件(Dll). VB: V9.0 PB: V8.0 Delphi创建的文件,提供给VB9调用:C++创建的文件,提供给PB8调用. 一.VB部分 C ...