讲师中心 微信公众号

工具推荐

视频效率加速
立刻MV
立刻MV

低成本歌曲 MV、视频生成

updream

一键生成高质量推广成片

AniShort
AniShort

AI短剧协同制作平台

剧云
剧云

中文短剧剧本制作平台

什么是间隙锁(Gap Lock)?它解决了什么问题?

陌丽吖_9591

陌丽吖_9591

发布时间:2025-09-10 08:06:01

|

904人浏览过

|

来源于php中文网

原创

间隙锁通过锁定索引记录间的“间隙”防止其他事务插入新记录,从而避免幻读。在REPEATABLE READ隔离级别下,执行范围查询时,InnoDB不仅锁定行记录,还锁定记录之间的间隙、首记录前和末记录后的范围。例如查询id BETWEEN 10 AND 20时,会锁定(5,12)和(12,25)等间隙(假设有id为5、12、25的记录),阻止其他事务插入id在该范围内的新行。间隙锁基于B+树索引实现,影响范围可能超出预期,增加锁冲突风险。实际应用中,可通过调整隔离级别至READ COMMITTED、优化索引设计、缩小事务范围、避免不必要的锁定、监控锁状态及分批处理等方式优化间隙锁带来的并发问题。

什么是间隙锁(gap lock)?它解决了什么问题?

间隙锁(Gap Lock)是InnoDB存储引擎在实现特定事务隔离级别(主要是

REPEATABLE READ
)时,为了解决幻读(Phantom Read)问题而引入的一种锁机制。简单来说,它锁定的不是具体的某一行记录,而是索引记录之间的“间隙”,或者说是某个范围。这能有效防止新的记录被插入到这个被锁定的范围内,从而保证事务在多次读取同一范围数据时,看到的数据集是一致的。

间隙锁的出现,坦白讲,是数据库设计者在追求数据一致性与并发性之间找到的一个平衡点。当我们的事务需要确保在某个数据范围内,不会有新的数据凭空出现或消失时,间隙锁就发挥了它的作用。它解决了这样一个痛点:即便我们已经锁定了查询到的所有行记录,但在并发环境下,如果其他事务在这个范围里插入了新行,我们的后续查询依然会“看到”这些新行,这就是幻读。间隙锁正是为了弥补这种“空隙”而生的。

间隙锁是如何避免幻读(Phantom Read)的?

要理解间隙锁如何避免幻读,我们得先搞清楚幻读到底是什么。想象一下,你在一个银行系统里,先查询了所有余额在100到200之间的账户。如果此时,另一个柜员恰好新开了一个账户,余额是150,并提交了。那么当你再次查询同样范围的账户时,你会发现多了一个之前没见过的账户。这就是幻读,你的事务在逻辑上认为的“不变”被打破了。

间隙锁正是为了防止这种情况发生。当一个事务在

REPEATABLE READ
隔离级别下,执行一个范围查询并需要锁定这些数据(比如
SELECT ... WHERE id BETWEEN 10 AND 20 FOR UPDATE;
),InnoDB不仅仅会锁定
id
在10到20之间的所有现有记录,它还会锁定这些记录之间的“间隙”,以及10之前的间隙和20之后的间隙(如果它们是边界)。

具体来说,如果你的表里有

id
为5, 12, 25的记录,当你查询
id BETWEEN 10 AND 20
时,间隙锁会锁定:

  • (5, 12)
    这个间隙:防止新的
    id
    在5到12之间插入。
  • (12, 25)
    这个间隙:防止新的
    id
    在12到25之间插入。
  • 如果查询范围是
    id > 10
    ,那么它会锁定
    (10, 12)
    ,
    (12, 25)
    ,以及
    (25, +∞)
    。

这样一来,无论其他事务尝试在

(5, 12)
或
(12, 25)
这两个区间内插入任何新记录,都会被当前事务的间隙锁阻塞,直到当前事务提交或回滚。这确保了在当前事务的生命周期内,你再次执行相同的范围查询时,不会看到任何“凭空出现”的新行,从而有效杜绝了幻读。

win可用的mysql指令skill
win可用的mysql指令skill

安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。

下载

间隙锁的工作原理与影响范围是怎样的?

间隙锁的工作原理,说白了,就是InnoDB利用了B+树索引的特性。它不是在内存中画一个“锁定的区域”,而是通过在索引结构中的特定位置设置锁标记来实现的。当一个事务需要锁定某个范围时,InnoDB会找到这个范围的起始和结束索引键值,然后锁定这些键值所代表的记录以及它们之间的“空隙”。值得注意的是,间隙锁是作用于索引的,所以一个高效的索引设计对于间隙锁的性能至关重要。

间隙锁的影响范围,有时候会超出我们的预期,这正是它可能导致死锁和并发问题的原因。它会锁定:

  1. 索引记录之间的间隙:这是最核心的部分。
  2. 第一个索引记录之前的间隙:如果你的查询范围从索引的最小值开始,或者查询的起始值小于表中最小的索引值,那么从负无穷到第一个索引记录之间的间隙也会被锁定。
  3. 最后一个索引记录之后的间隙:同理,如果查询范围到索引的最大值结束,或者查询的结束值大于表中最大的索引值,那么从最后一个索引记录到正无穷之间的间隙也会被锁定。

举个例子,假设我们有一个

users
表,
id
列是主键,有数据
id = 1, 5, 10, 15
。 如果一个事务执行
SELECT * FROM users WHERE id > 7 AND id < 12 FOR UPDATE;
那么,InnoDB会锁定:

  • 记录
    id=10
    (这是一个行锁)。
  • (5, 10)
    这个间隙。
  • (10, 15)
    这个间隙。 这意味着,在事务提交前,其他事务无法插入
    id
    为6、7、8、9、11、12、13、14的记录。可以看到,间隙锁锁定了一个比我们查询结果更大的范围,这在某些高并发场景下,确实会增加锁冲突的可能性。

在实际应用中,我们应该如何理解和优化间隙锁?

理解间隙锁的机制,对于编写高性能、无死锁的SQL至关重要。在实际应用中,我们经常会遇到因为间隙锁导致的并发问题,比如死锁或者事务长时间等待。

  1. 何时触发间隙锁?

    • 在
      REPEATABLE READ
      隔离级别下。
    • 当执行范围查询(
      WHERE col > X AND col < Y
      ,
      WHERE col LIKE 'prefix%'
      等)时。
    • 当对非唯一索引进行等值查询,且查询条件命中了多个记录,或者没有命中任何记录时,也会产生间隙锁。比如
      SELECT * FROM users WHERE status = 'pending' FOR UPDATE;
      如果
      status
      是非唯一索引,并且有很多
      pending
      的记录,那么这些记录以及它们之间的间隙都会被锁定。
    • INSERT
      操作在某些情况下也会产生间隙锁,例如在插入新记录时,为了检查唯一性约束,可能会锁定插入位置附近的间隙。
  2. 优化策略:

    • 考虑隔离级别: 如果你的业务场景能够接受较低的隔离级别(例如
      READ COMMITTED
      ),并且幻读不是一个核心问题,那么切换到
      READ COMMITTED
      可以完全禁用间隙锁(但仍会保留行锁)。这能显著提高并发性,但需要权衡数据一致性风险。
    • 精准索引设计: 确保你的查询能够尽可能地利用索引,并且查询条件能够精确匹配索引,避免全表扫描或大范围的索引扫描。对于唯一索引的等值查询,InnoDB只会加行锁,不会有间隙锁。
    • 缩小事务范围: 尽量让事务简短,减少锁持有的时间。长时间运行的事务,尤其是涉及范围查询的,会长时间持有间隙锁,极大地影响并发。
    • 避免不必要的锁定: 只有在确实需要防止幻读或数据不一致时,才使用
      FOR UPDATE
      或
      LOCK IN SHARE MODE
      。
    • 监控锁情况: 使用
      SHOW ENGINE INNODB STATUS
      可以查看当前的锁等待和死锁信息,帮助我们定位和分析间隙锁引起的问题。通过分析
      LATEST DETECTED DEADLOCK
      部分,我们可以看到是哪些事务、哪些SQL语句因为间隙锁而发生了死锁。
    • 批量操作: 对于需要更新或删除大量数据的操作,考虑分批处理,每次处理一小部分数据,可以减少单次事务持有间隙锁的时间和范围。

间隙锁是一个强大的工具,它在保证数据一致性方面功不可没,但同时它也是一把双刃剑,不恰当的使用或不理解其工作原理,很容易导致性能瓶颈。所以,深入理解它,并结合业务场景进行优化,是我们每个开发者都需要掌握的技能。

热门AI工具

更多
Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

4983

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1011

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

1309

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

7041

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

3703

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

7040

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

9841

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

1330

2024.04.29

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn