首页 > 其他分享 >面试突击:MVCC 和间隙锁有什么区别?

面试突击:MVCC 和间隙锁有什么区别?

时间:2023-04-02 10:32:52浏览次数:45  
标签:事务 并发 间隙 幻读 面试 MVCC 数据

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,数据
From: https://blog.51cto.com/vipstone/6164406

相关文章

  • 这可能是最全面的Spring面试题总结了
    Spring是什么?Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。Spring的优点通过控制反转和依赖注入实现松耦合。支持面向切面的编程,并且把应用业务逻辑和系统服务分开。通过切面和模板减少样板式代码。声明式事务的支持。可以从单调繁冗的事务管理代码中解脱......
  • 软件测试面试之问——角色扮演
      作为软件测试工程师,在求职面试中经常会被问到这样一个问题:你认为测试工程师在企业中扮演着什么样的角色呢?  某度百科是这样概括的:“软件测试工程师在一家软件企业中担当的是‘质量管理’角色,及时发现软件问题并及时督促更正,确保产品的正常运作。”测试工程师之角色扮演(一......
  • sql面试题目
    sql逻辑:createtableods.product(product_idint,product_namevarchar(255))ENGINE=InnoDBDEFAULTCHARSET=utf8mb3;insertintoods.productvalues(1,'LCPhone');insertintoods.productvalues(2,'LCT-Shirt');select*fromods.product;cre......
  • 别逛了,送你一份2023年Java核心篇JVM(虚拟机)面试题整理
    Java内存区域说一下JVM的主要组成部分及其作用?JVM包含两个子系统和两个组件,两个子系统为Classloader(类装载)、Executionengine(执行引擎);两个组件为Runtimedataarea(运行时数据区)、NativeInterface(本地接口)。●Classloader(类装载):根据给定的全限定名类名(如:java.......
  • 面试笔记-Docker(Ⅱ)
    上篇文章已经成功build了image并且创建了container运行成功,我们现在进行接下来的工作目录挂载使用Docker运行后,我们改了项目代码不会立刻生效,需要重新build和run,很是麻烦。容器里面产生的数据,例如log文件,数据库备份文件,容器删除后就丢失了。......
  • 面试题
    目录可变类型与不可变类型常用的魔法方法类中的装饰器双写一致性断点续传内网穿透缓存击穿http与https数据库如何处理的?用过什么云产品看看数据库celery多线程mysql1千万w,性别字段(男女),查询时候,这个字段要不要加索引实现踢下线实现黑名单功能深浅拷贝是什么魔法方法new和init有什......
  • 面试笔记-Docker(Ⅰ)
    打包写好的项目基础配置安装指定版本的node.jsdockerpullnode:18.15运行刚才pull到的镜像,即创建一个containerdockerrun-itd--namenode-testnode:18.15-i:表示以交互模式运行容器(让容器的标准输入保持打开)-d:表示后台运行容器,并返回容器ID-t:为容器重新分配一个伪......
  • 三天吃透MySQL面试八股文
    什么是MySQLMySQL是一个关系型数据库,它采用表的形式来存储数据。你可以理解成是Excel表格,既然是表的形式存储数据,就有表结构(行和列)。行代表每一行数据,列代表该行中的每个值。列上的值是有数据类型的,比如:整数、字符串、日期等等。数据库的三大范式第一范式1NF确保数据库表字段......
  • 我如何回答编码面试问题的框架
    我讨厌编码面试已经不是什么秘密了。他们是一种糟糕的招聘方式并且容易出现误报(也就是不必要地拒绝优秀候选人)。对于大多数公司来说,提出白板式的问题并不符合他们的最大利益。不幸的是,它们是行业标准。作为一名软件工程师,您必须在求职过程中回答白板上的问题。所以,这是我如何擅......
  • 测试面试题
    软件测试1、软件的定义?软件是一系列按特定顺序组织的计算机数据和指令的集合,包括与计算机系统操作有关的程序、规程、规则、文件、文档和数据。软件被划分为系统软件、应用软件和中间件。软件不仅包括电脑程序,还包括与这些程序相关的文档,可简单地理解为程序和文档的集合。2、......