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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 面试突击: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版),持续更新...
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
数据库 数据安全/隐私保护
共享锁和排他锁在实际应用中的优缺点
【10月更文挑战第16天】共享锁和排他锁是多进程和多线程环境中常用的同步机制,它们各自具有优点和缺点。在实际应用中,需要根据具体的场景和需求选择合适的锁类型。在选择锁时,需要考虑读写比例、数据一致性要求、系统性能、死锁风险等因素,并结合实际情况进行优化和调整。通过合理使用锁,可以提高系统的并发性、数据一致性和性能。
|
7月前
|
存储 人工智能 关系型数据库
10个行锁、死锁案例⭐️24张加锁分析图🚀彻底搞懂Innodb行锁加锁规则!
10个行锁、死锁案例⭐️24张加锁分析图🚀彻底搞懂Innodb行锁加锁规则!
|
7月前
|
存储 关系型数据库 MySQL
分布式事物【悲观锁、乐观锁、读锁、写锁、间隙锁、临键锁 、 表锁、行锁、页面锁、 如何避免死锁】(二)-全面详解(学习总结---从入门到深化)
分布式事物【悲观锁、乐观锁、读锁、写锁、间隙锁、临键锁 、 表锁、行锁、页面锁、 如何避免死锁】(二)-全面详解(学习总结---从入门到深化)
340 0
|
7月前
|
存储 SQL 关系型数据库
索引和事务究竟是何方神圣?那可是面试中的常客!
索引和事务究竟是何方神圣?那可是面试中的常客!
79 1
索引和事务究竟是何方神圣?那可是面试中的常客!
|
7月前
|
关系型数据库 MySQL 数据库
|
7月前
|
关系型数据库 MySQL 数据库
MySQL锁三部曲:临键、间隙与记录的奇妙旅程
MySQL锁三部曲:临键、间隙与记录的奇妙旅程
589 0
|
7月前
|
算法 Java
【面试问题】锁如何优化?
【1月更文挑战第27天】【面试问题】锁如何优化?
|
存储 SQL 关系型数据库
面试官:MySQL 啥时候用记录锁,啥时候用间隙锁?
MySQL 啥时候会用记录锁,啥时候会用间隙锁,啥时候又会用 Next-Key 锁呢?今天我们就来做一些测试,弄清楚这个问题。
面试官:MySQL 啥时候用记录锁,啥时候用间隙锁?
|
SQL Java 数据库连接
数据库相关锁总结(共享锁,排它锁,更新锁,意向锁,计划锁),看完这篇将会对锁产生更深的理解
数据库相关锁总结(共享锁,排它锁,更新锁,意向锁,计划锁),看完这篇将会对锁产生更深的理解
115 0
MySQL沉浸式面试:隔离级别、锁、索引原理连环炮你扛得住吗?
基础篇主要是侧重基础知识,原理篇是有一定基础后的递进,通过学习本篇,不仅可以进一步了解MySQL的各项特性,还能为接下来的容灾调优打下坚实的基础。 现在,就让我们继续跟随阿柴进行这场沉浸式面试吧。

热门文章

最新文章