当前位置: 首页 > article >正文

MySQL间隙锁入手,拿下间隙锁面试与实操

一、MySQL 间隙锁,究竟是什么?

在 MySQL 的世界里,间隙锁(Gap Lock)就像是一个默默守护数据一致性的卫士,看似低调,却在并发控制中扮演着至关重要的角色。​

想象一下,你去图书馆借书,书架上的书按照编号依次排列。你想要借编号在 10 - 20 之间的书,这时候图书馆管理员为了保证你借到的书是符合你要求的,他不仅会把编号 10 - 20 的书标记为已被你预订(就像行锁锁住了具体的数据行),还会把编号 9 和 21 之间的空位也标记起来(这就相当于间隙锁),防止其他人在你借书期间把一本编号为 15 的新书插入到这个空位中,导致你借到的书不符合你原本要求的范围。​

从官方文档的角度来看,间隙锁是 InnoDB 存储引擎在可重复读(Repeatable Read)事务隔离级别下用来防止幻读(Phantom Read)的一种锁机制。当一个事务执行范围查询时,MySQL 会为查询结果集中的每个记录都加上间隙锁,即锁定了记录之间的间隙(Gap)。​
从原理上来说,间隙锁锁定的是索引记录之间的间隙,或者是第一个索引记录之前、最后一个索引记录之后的空间。例如,有一个表中的记录按照某个列的升序排列,事务 A 执行以下查询:

SELECT * FROM table WHERE col BETWEEN 10 AND 20 FOR UPDATE;

MySQL 会为查询结果中的记录加上间隙锁,即锁定了 10 到 20 之间的间隙。这样,其他事务在这个范围内插入新记录时会被阻塞,直到事务 A 提交或者回滚。需要注意的是,间隙锁只在使用索引的情况下生效。如果查询条件没有使用索引,MySQL 不会使用间隙锁 。​

间隙锁的作用主要是防止幻读。幻读指的是在一个事务中,多次执行相同的查询,由于其他事务的插入或删除操作,导致每次查询的结果集不一样,就好像出现了幻觉一样。间隙锁通过锁定记录之间的间隙,阻止其他事务在这个间隙中插入新记录,从而保证了在一个事务中多次执行相同的范围查询时,结果集的一致性。

二、间隙锁的使用场景与实战演练

2.1 实际应用场景​

在实际应用中,间隙锁在许多场景下都发挥着重要作用。比如在电商系统的订单模块中,当查询某个时间段内的订单列表时,为了保证在查询过程中不会有新的订单插入到这个时间段内,从而影响查询结果的一致性,就可以使用间隙锁。又比如在库存管理系统中,当查询某个库存数量范围的商品时,间隙锁可以防止其他事务在这个范围内插入或修改商品库存记录,确保库存数据的准确性 。

2.2 建表示例与加锁分析​

接下来,我们通过一个具体的建表示例来深入了解间隙锁在不同事务隔离级别下的加锁情况。​
首先,创建一个名为products的表,用于存储商品信息,表结构如下:

CREATE TABLE products (id INT PRIMARY KEY AUTO_INCREMENT,product_name VARCHAR(100) NOT NULL,stock INT NOT NULL,price DECIMAL(10, 2) NOT NULL
);

插入一些数据:

INSERT INTO products (product_name, stock, price) VALUES
('Product A', 10, 100.00),
('Product B', 20, 200.00),
('Product C', 30, 300.00);
2.2.1 可重复读(Repeatable Read)隔离级别​

在可重复读隔离级别下,我们进行如下操作:

-- 开启事务
START TRANSACTION;
-- 范围查询并加锁
SELECT * FROM products WHERE stock BETWEEN 15 AND 25 FOR UPDATE;

在这个例子中,stock列上有索引(假设我们创建了索引idx_stock),当执行上述查询时,MySQL 会对stock值在 15 到 25 之间的记录加上间隙锁,同时对符合条件的记录加上记录锁(如果有记录满足条件)。具体来说,会锁定stock值为 10 和 20 之间的间隙,以及 20 和 30 之间的间隙,防止其他事务在这些间隙中插入新的记录。​

2.2.2 读已提交(Read Committed)隔离级别​

将事务隔离级别设置为读已提交:

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 开启事务
START TRANSACTION;
-- 范围查询并加锁
SELECT * FROM products WHERE stock BETWEEN 15 AND 25 FOR UPDATE;

在读已提交隔离级别下,MySQL 不会使用间隙锁,只会对符合条件的记录加上记录锁。也就是说,只会锁定stock值为 20 这条记录(如果存在满足条件的记录),而不会锁定记录之间的间隙,其他事务可以在间隙中插入新的记录 。​

2.2.3 插入操作​

在可重复读隔离级别下,当执行插入操作时,如果插入的值落在间隙锁的范围内,会被阻塞。例如:

-- 事务A
START TRANSACTION;
SELECT * FROM products WHERE stock BETWEEN 15 AND 25 FOR UPDATE;
-- 事务B
START TRANSACTION;
INSERT INTO products (product_name, stock, price) VALUES ('New Product', 22, 220.00); -- 会被阻塞

在这个例子中,事务 A 对stock在 15 到 25 之间的范围加了间隙锁,事务 B 试图插入stock值为 22 的记录,由于该值落在间隙锁的范围内,所以事务 B 的插入操作会被阻塞,直到事务 A 提交或回滚 。​

2.2.4 更新操作​

同样在可重复读隔离级别下,更新操作如果涉及到间隙锁范围内的记录,也会受到影响。例如:

-- 事务A
START TRANSACTION;
SELECT * FROM products WHERE stock BETWEEN 15 AND 25 FOR UPDATE;
-- 事务B
START TRANSACTION;
UPDATE products SET stock = 22 WHERE product_name = 'Product B'; -- 会被阻塞

事务 A 对stock在 15 到 25 之间的范围加了间隙锁,事务 B 试图更新Product B的stock值为 22,由于更新后的值落在间隙锁的范围内,所以事务 B 的更新操作会被阻塞 。​

三、解锁面试:巧妙回答间隙锁问题​

在面试中,当被问到关于 MySQL 间隙锁的问题时,面试官通常希望考察你对数据库并发控制和事务隔离的理解,以及你在实际应用中解决问题的能力。因此,回答时要清晰、有条理,重点突出间隙锁的概念、原理、应用场景以及与其他锁机制的区别 。

3.1 回答思路​

首先,简要介绍间隙锁的基本概念,强调它是 InnoDB 存储引擎在可重复读事务隔离级别下用于防止幻读的一种锁机制。例如:“间隙锁是 InnoDB 在可重复读事务隔离级别下,为了防止幻读而引入的一种锁。它锁定的是索引记录之间的间隙,而不是具体的记录。”​
接着,阐述间隙锁的工作原理,包括锁定的范围和方式。可以结合具体的 SQL 示例进行说明,如:“当执行SELECT * FROM table WHERE col BETWEEN 10 AND 20 FOR UPDATE;这样的范围查询时,MySQL 会对col值在 10 到 20 之间的记录加上间隙锁,同时对符合条件的记录加上记录锁(如果有记录满足条件)。具体来说,会锁定col值为 10 和 20 之间的间隙,以及 20 和 30 之间的间隙,防止其他事务在这些间隙中插入新的记录 。”​
然后,提及间隙锁的应用场景,展示你对其实际用途的理解。比如:“在电商系统的订单模块中,当查询某个时间段内的订单列表时,为了保证在查询过程中不会有新的订单插入到这个时间段内,从而影响查询结果的一致性,就可以使用间隙锁。”​
最后,对比间隙锁与其他锁机制(如记录锁、表锁)的区别,进一步体现你对锁机制的全面掌握。例如:“记录锁锁定的是具体的索引记录,而间隙锁锁定的是索引记录之间的间隙;表锁的粒度较大,会锁定整个表,而间隙锁的粒度较小,只锁定特定的间隙范围 。”​

3.2 示例回答​

“MySQL 的间隙锁是 InnoDB 存储引擎在可重复读事务隔离级别下,为了防止幻读而引入的一种锁机制。简单来说,间隙锁锁定的是索引记录之间的间隙,而不是具体的记录。​
当我们执行一个范围查询时,比如SELECT * FROM products WHERE stock BETWEEN 15 AND 25 FOR UPDATE;,如果stock列上有索引,MySQL 会对stock值在 15 到 25 之间的记录加上间隙锁,同时对符合条件的记录加上记录锁(如果有记录满足条件)。具体而言,它会锁定stock值为 10 和 20 之间的间隙,以及 20 和 30 之间的间隙,这样其他事务就无法在这些间隙中插入新的记录,从而避免了幻读的发生 。​
在实际应用中,间隙锁在很多场景下都非常有用。例如在电商系统的库存管理中,当查询某个库存数量范围的商品时,间隙锁可以防止其他事务在这个范围内插入或修改商品库存记录,确保库存数据的准确性 。​
与其他锁机制相比,记录锁主要锁定的是具体的索引记录,而间隙锁关注的是记录之间的间隙;表锁则是锁定整个表,粒度较大,而间隙锁的粒度相对较小,只针对特定的间隙范围进行锁定 。总的来说,间隙锁在保证数据一致性和防止幻读方面发挥着重要作用,但在使用时也需要注意它可能对并发性能产生的影响 。”​

3.3 补充说明​

在回答完上述内容后,如果还有时间和机会,可以进一步补充一些关于间隙锁的注意事项或优化建议,如:​
间隙锁对性能的影响:间隙锁虽然能有效防止幻读,但由于它会锁定索引记录之间的间隙,可能会导致其他事务在插入新记录时被阻塞,从而影响数据库的并发性能。在高并发场景下,需要特别关注间隙锁的使用,避免出现性能瓶颈 。​
优化建议:为了减少间隙锁对性能的影响,可以尽量使用唯一索引进行查询,因为在唯一索引上使用等值查询时,InnoDB 会使用记录锁而不是间隙锁;合理设计数据库表结构和索引,避免不必要的范围查询;调整事务隔离级别,如果业务对数据一致性要求不是特别高,可以选择读已提交隔离级别,此时 MySQL 不会使用间隙锁 。​

MySQL 间隙锁作为一种在并发控制中防止幻读的重要机制,在数据库事务处理中起着关键作用。它通过锁定索引记录之间的间隙,有效避免了在可重复读事务隔离级别下因其他事务插入新记录而导致的幻读问题 。

相关文章:

MySQL间隙锁入手,拿下间隙锁面试与实操

一、MySQL 间隙锁,究竟是什么? 在 MySQL 的世界里,间隙锁(Gap Lock)就像是一个默默守护数据一致性的卫士,看似低调,却在并发控制中扮演着至关重要的角色。​ 想象一下,你去图书馆借…...

词法分析和词性标注 自然语言处理

目录 一. 概述 1 不同语言的词法分析 2 英语的形态分析 英语单词的形态还原(和正常英语的词法变化一样) 1.有规律变化单词的形态还原 ​编辑 2.动词、名词、形容词、副词不规则变化单词的形态还原 3.对于表示年代&…...

QT聊天项目DAY14

1. 客户端登录 1.1 初始化玩家头像 将头像的大小固定在250 * 250 void InitHeadImage(); // 初始化头像/* 初始化头像 */ void LoginWidget::InitHeadImage() {// 加载头像QPixmap OriginalPixmap(":/Chat/Images/head_5.jpg");OriginalPixmap …...

架构设计技巧——架构设计模板

一份实用、高效、覆盖核心要素的架构设计模板是确保设计质量、促进团队沟通和指导实施的关键。以下是一个经过提炼的架构设计文档核心模板框架,结合了业界最佳实践,并强调灵活裁剪: 架构设计文档模板 (核心框架) 文档标识 项目/系统名称&a…...

交易系统开发:跨境资本的高速通道架构解密

连接纽约、香港与内陆的金融管道工程 总收益互换(TRS)在港美股投资中扮演着跨境资本流动的“隐形桥梁”。本文基于真实跨境券商系统开发实践,深入解析支持多市场、多币种、多通道的TRS平台架构设计与业务解决方案。 一、港美股TRS的核心价值&…...

【Ragflow】27.RagflowPlus(v0.4.1):小版本迭代,问题修复与功能优化

概述 RagflowPlus v0.4.0 在发布后,收到了积极的反馈,同时也包含一些问题。 本次进行一轮小版本更新,发布 v0.4.1 版本,对已知问题进行修复,并对部分功能进行进一步优化。 开源地址:https://github.com/…...

易语言是什么?易语言能做什么?

易语言(EPL)是什么?​​ ​​易语言​​(Easy Programming Language,简称EPL)是一款​​面向中文用户的编程语言​​,由中国人吴涛于2000年开发,专为降低编程门槛设计。其核心特点是…...

【Oracle】数据仓库

个人主页:Guiat 归属专栏:Oracle 文章目录 1. 数据仓库概述1.1 为什么需要数据仓库1.2 Oracle数据仓库架构1.3 Oracle数据仓库关键技术 2. 数据仓库建模2.1 维度建模基础2.2 星形模式设计2.3 雪花模式设计2.4 缓慢变化维度(SCD)处…...

基于开源AI大模型AI智能名片S2B2C商城小程序源码的中等平台型社交电商运营模式研究

摘要:本文聚焦中等平台型社交电商,探讨其与传统微商及大型社交电商平台的差异,尤其关注产品品类管理对代理运营的影响。通过引入开源AI大模型、AI智能名片与S2B2C商城小程序源码技术,构建智能化运营体系。研究结果表明&#xff0c…...

typeof运算符 +unll和undefined的区别

typeof运算符 JavaScript 有三种方法,可以确定一个值到底是什么类型。而我们 现在需要接触到的就是typeof 数值返回number 1 typeof 123 // "number" 字符串返回string 1 typeof 123 // "string" 布尔值返回boolean 1 typeof fal…...

Vite 双引擎架构 —— Esbuild 概念篇

Vite 底层采用 双引擎架构,核心构建引擎是 Esbuild 和 Rollup,二者在开发和生产环境中分工协作,共同实现高性能构建。不可否认,作为 Vite 的双引擎之一,Esbuild 在很多关键的构建阶段(如依赖预编译、TS 语法转译、代码…...

Life:Internship finding

1. 前言 fishwheel writes this Blog to 记录自分自身在研二下找实习的经历。When 写这篇 Blog 的时候我的最后一搏也挂掉了,只能启用保底方案了。When I 打开我的邮箱时,发现里面有 nearly 100 多封与之相关的邮件,顿时感到有些心凉&#x…...

阿里云Alibaba Cloud安装Docker与Docker compose【图文教程】

个人记录 进入控制台,找到定时与自动化任务 进入‘安装/卸载扩展程序’ 点击‘安装扩展程序’ 选择docker社区版,点击下一步与确定,等待一会 安装成功 查询版本 查询docker sudo docker version查询docker compose sudo docker compo…...

GitHub 趋势日报 (2025年06月07日)

📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 603 netbird 459 dify 440 cognee 352 omni-tools 337 note-gen 239 ragbits 237 …...

Java编程之组合模式

引言 在软件开发的世界里,我们经常会遇到需要表示"部分-整体"层次结构的场景。比如文件系统中的文件和文件夹、图形界面中的各种组件、企业组织架构中的部门和员工等。这些场景都有一个共同的特点:我们需要以一种统一的方式来处理单个对象和由…...

Oracle 19c RAC集群ADG搭建

1、将主库的pfile和passwdfile发送到备库 #主库一节点操作 scp -P1234 /tmp/pfile2025.ora bak_ip:/home/oracle sco -P1234 /oracle/app/oracle/product/19.0.0/db/dbs/orapw$ORACLE_SID bak_ip:/oracle/app/oracle/product/19.0.0/db/dbs 2、备库修改参数文件成standby相关…...

ADB识别手机系统弹授权框-如何处理多重弹框叠加和重叠问题

ADB识别手机系统弹授权框-如何处理多重弹框叠加和重叠问题 --蓝牙电话SDK自动部署 上一篇:手机App-插入USB时自动授权点击确定按钮-使系统弹出框自动消失 下一篇:编写中。 一、前言 我们在上一篇《手机App-插入USB时自动授权点击确定按钮-使系统弹出框…...

Kaggle-Predicting Optimal Fertilizers-(多分类+xgboost+同一特征值多样性)

Predicting Optimal Fertilizers 题意: 给出土壤的特性,预测出3种最佳的肥料 数据处理: 1.有数字型和类别型,类别不能随意换成数字,独热编码。cat可以直接处理category类型。 2.构造一些相关土壤特性特征 3.由于la…...

uniapp+<script setup lang=“ts“>解决有数据与暂无数据切换显示,有数据加载时暂无数据闪现(先加载空数据)问题

声明showEmpty 为false&#xff0c;在接口返回处判断有数据时设置showEmpty 为false&#xff0c;接口返回数据为空则判断showEmpty 为true &#xff08;这样就解决有数据的时候会闪现暂无数据的问题啦&#xff09; <!--* Date: 2024-02-26 03:38:52* LastEditTime: 2025-06…...

详解鸿蒙Next仓颉开发语言中的动画

大家上午好&#xff0c;今天来聊一聊仓颉开发语言中的动画开发。 仓颉中的动画通常有两种方式&#xff0c;分别是属性动画和显示动画&#xff0c;我们今天以下面的加载动画为例&#xff0c;使用显示动画和属性动画分别实现一下&#xff0c;看看他们有什么区别。 显示动画 显示…...

Redis常见使用场景解析

1. 数据库缓存 Redis 作为典型的 Key-Value 型内存数据库,数据缓存是其最广为人知的应用场景。使用 Redis 缓存数据操作简便,通常将序列化后的对象以 string 类型存储。但在实际应用中,需注意以下关键要点: Key 设计:必须确保不同对象的 Key 具有唯一性,且尽量缩短长度,…...

C语言指针与数组sizeof运算深度解析:从笔试题到内存原理

前两天跟着数组指针的教程&#xff1a; // #self 视频里的笔试题 !!!vipint b12[3][4] {0};printf("%ld \n", sizeof(b12[0]));printf("%ld \n", sizeof(*b12));printf("%ld \n", sizeof(*(b12 1)));printf("%ld \n", sizeof(*(&am…...

起重机指挥人员在工作中需要注意哪些安全事项?

起重机指挥人员在作业中承担着协调设备运行、保障作业安全的关键职责&#xff0c;其安全操作直接关系到整个起重作业的安全性。以下从作业前、作业中、作业后的全流程&#xff0c;详细说明指挥人员需注意的安全事项&#xff1a; 一、作业前的安全准备 资质与状态检查&#xff…...

JVM内存区域与溢出异常详解

当然可以。以下是结合了程序计数器和Java内存区域以及内存溢出异常的详细解释&#xff1a; JVM内存区域与内存溢出异常 Java虚拟机&#xff08;JVM&#xff09;管理着不同类型的内存区域&#xff0c;每个区域都有其特定的功能和可能导致的内存溢出异常。 程序计数器&#xff…...

ES海量数据更新及导入导出备份

一、根据查询条件更新字段 from elasticsearch import Elasticsearch import redis import json# 替换下面的用户名、密码和Elasticsearch服务器地址 username elastic password password es_host https://127.0.0.2:30674# 使用Elasticsearch实例化时传递用户名和密码 es…...

Java线程池核心原理与最佳实践

Java 线程池详解 线程池是Java并发编程的核心组件&#xff0c;它能高效管理线程生命周期&#xff0c;避免频繁创建销毁线程的开销&#xff0c;提升系统性能和资源利用率。 一、线程池核心优势 降低资源消耗&#xff1a;复用已创建的线程&#xff0c;减少线程创建销毁开销提高…...

JAVA-springboot log日志

SpringBoot从入门到精通-第8章 日志的操作 一、Spring Boot默认的日志框架 SpringBoot支持很多种日志框架&#xff0c;通常情况下&#xff0c;这些日志框架都是由一个日志抽象层和一个日志实现层搭建而成的&#xff0c;日志抽象层是为记录日志提供的一套标准且规范的框架&…...

1.springmvc基础入门(一)

1.Spring MVC概念 Spring MVC 是 Spring Framework 提供的 Web 组件&#xff0c;全称是 Spring Web MVC&#xff0c;是⽬前主流的实现 MVC 设计模式的框架&#xff0c;提供前端路由映射、视图解析等功能。 Java Web 开发者必须要掌握的技术框架。 2.Spring MVC 功能 MVC&am…...

AI 时代下语音与视频伪造的网络安全危机

引言 在人工智能技术的推动下&#xff0c;语音合成、视频生成等技术取得了突破性进展&#xff0c;Deepfake、AI 语音克隆等工具让语音和视频伪造变得愈发简单且逼真。这些技术在娱乐、影视等领域带来便利的同时&#xff0c;也被不法分子利用&#xff0c;引发了一系列网络安全问…...

模块缝合-把A模块换成B模块(没写完)

把MLP Head替换为KAN 1.在model文件下新建一个python文件 2.把 模块文件里的整个KAN代码复制到新的python文件中 3.在开头导入 from model.KAN(新建文件名&#xff09; import KAN&#xff08;新建文件中的类名&#xff09; 4.sys.path.append(r"D: Icode(Kansformer"…...