mysql fetch into 详解MySQL InnoDB间隙锁(Gap Lock)
mysql fetch into 详解MySQL InnoDB间隙锁(Gap Lock)
间隙锁是实现幻读防护、保证事务隔离级别的核心机制,但也因“锁范围扩大”特性,成为并发问题的高频诱因。本文将从间隙锁的核心定义、触发条件、工作机制出发,结合实战案例拆解间隙锁的使用场景与避坑方案,详细介绍间隙锁。

一、间隙锁是什么?1. 定义
间隙锁(Gap Lock)是在RR(可重复读)隔离级别下 为解决“幻读”问题引入的锁机制,它锁定的不是“某一行数据”,而是索引记录之间的间隙(空区间),甚至是不存在的记录对应的区间。可以比喻为:把数据表的索引记录比作停车场的车位(按编号排序:1、3、5、7),间隙锁就像“锁定车位之间的空位置”——比如锁定2号车位(1和3之间)、4号车位(3和5之间),防止其他事务在这些空位置“新增车辆(插入数据)”,从而避免幻读。
2. 核心作用:解决幻读问题
幻读是指同一事务内,连续执行相同的范围查询,第二次查询会返回第一次查询没有的“新插入数据”(即使事务未提交)。例如:
-- 事务A(RR隔离级别)
BEGIN;
-- 第一次查询:查询id>2且id2 AND id2 AND id<6 FOR UPDATE;
COMMIT;
间隙锁的作用就是:事务A执行范围查询时,不仅锁定已存在的id=3、5,还会锁定“2-3、3-5、5-6”的间隙,禁止事务B插入id=4的记录,从而杜绝幻读。
间隙锁生效前提:
二、间隙锁的核心机制1. 间隙的判定规则
间隙的范围由索引记录的排序 决定,以主键索引为例(假设表中有id=1、3、5、7的记录):
关键点:
2. 间隙锁的触发场景
只有执行范围条件的锁定操作 时,才会触发间隙锁,常见场景:
… FOR (排他锁定读); … LOCK IN SHARE MODE(共享锁定读);/ 语句使用范围条件(如WHERE id>2 AND … ON KEY (唯一键冲突时,会对冲突间隙加锁)。
反例(不触发间隙锁):
3. 间隙锁与行锁、Next-Key Lock的关系
的锁机制中,间隙锁不是孤立的,通常与行锁组合成 Next-Key Lock(临键锁)——这是默认的锁定方式:
Next-Key Lock = 行锁(Record Lock) + 间隙锁(Gap Lock)

以id=3为例,Next-Key Lock会锁定:
规则:
示例:Next-Key Lock的锁定范围
假设表t的主键id有记录:1、3、5、7,执行:
SELECT * FROM t WHERE id>2 AND id<6 FOR UPDATE;
实际锁定的范围(Next-Key Lock):
id=3的行锁 + (1,3)的间隙锁;id=5的行锁 + (3,5)的间隙锁;(5,6)的间隙锁(因为查询上限是6,需阻止插入5-6之间的记录)。
最终锁定的完整区间:(1,6),禁止插入id=2、4、6的记录。
三、间隙锁案例分析场景1:等值查询触发间隙锁(记录不存在)
-- 表t:主键id,现有记录1、3、5、7
-- 事务A
BEGIN;
-- 等值查询id=4(不存在),触发间隙锁:锁定(3,5)
SELECT * FROM t WHERE id=4 FOR UPDATE;
-- 事务B(此时执行会阻塞,直到事务A提交/回滚)
INSERT INTO t(id) VALUES(4); -- 阻塞(插入(3,5)间隙)
INSERT INTO t(id) VALUES(2); -- 正常执行(不在(3,5)间隙)
原因:虽然是等值查询,但记录不存在,会锁定该值对应的间隙,防止其他事务插入该记录,避免后续出现幻读。
场景2:范围更新触发间隙锁(导致死锁)
-- 表t:主键id,现有记录1、3、5、7
-- 事务A
BEGIN;
-- 更新id>2且id2 AND id4且id4 AND id<8;
-- 事务A尝试插入id=4(锁定(3,5)间隙,与事务B冲突)
INSERT INTO t(id) VALUES(4); -- 死锁触发
死锁原因:
场景3:无索引触发表级间隙锁(锁表)
-- 表t:无索引的name字段,现有记录:'zhangsan'、'lisi'、'wangwu'
-- 事务A
BEGIN;
-- 范围查询name,无索引,InnoDB全表扫描,锁定整个表的间隙(视为一个大间隙)
SELECT * FROM t WHERE name LIKE 'z%' FOR UPDATE;
-- 事务B(所有插入/更新都会阻塞)
INSERT INTO t(name) VALUES('zhaoliu'); -- 阻塞
UPDATE t SET name='test' WHERE name='lisi'; -- 阻塞
原因:间隙锁仅对索引字段生效,无索引时,会将整个表视为一个间隙,触发“表级间隙锁”,等同于锁表。
场景4:唯一索引的特殊规则(间隙锁降级)
对于唯一索引(主键/唯一键) 的等值查询mysql fetch into,会优化间隙锁:
示例:
-- 表t:主键id,现有记录1、3、5、7
-- 事务A:等值查询id=3(存在),仅加行锁
SELECT * FROM t WHERE id=3 FOR UPDATE;
-- 事务B:插入id=2((1,3)间隙),正常执行(无间隙锁阻塞)
INSERT INTO t(id) VALUES(2); -- 成功
-- 事务A:等值查询id=4(不存在),仅加(3,5)间隙锁
SELECT * FROM t WHERE id=4 FOR UPDATE;
-- 事务B:插入id=4(阻塞),插入id=6(正常)
INSERT INTO t(id) VALUES(4); -- 阻塞
INSERT INTO t(id) VALUES(6); -- 成功

四、间隙锁的核心配置与优化1. 关闭间隙锁的两种方式(按需选择)
间隙锁虽能解决幻读,但会降低并发性能,可根据业务场景关闭:
方式1:降低隔离级别(推荐)
将隔离级别改为 RC(读已提交)mysql fetch into,会禁用间隙锁,仅保留行锁:
-- 临时修改(会话级别)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 永久修改(my.cnf)
[mysqld]
transaction-isolation = READ-COMMITTED
优缺点:
方式2:启用(不推荐)
[mysqld]
innodb_locks_unsafe_for_binlog = 1
注意:该参数已被MySQL 8.0废弃,仅兼容旧版本,且可能导致主从数据不一致,禁止在生产环境使用。
2. 优化间隙锁的最佳实践(1)优先使用唯一索引/主键进行等值查询
唯一索引的等值查询会降级间隙锁为行锁mysql fetch into,减少锁范围:
-- 推荐(主键等值查询,仅行锁)
SELECT * FROM t WHERE id=3 FOR UPDATE;
-- 避免(范围查询,触发Next-Key Lock)
SELECT * FROM t WHERE id>=3 AND id<=3 FOR UPDATE;
(2)为查询字段添加索引mysql fetch into 详解MySQL InnoDB间隙锁(Gap Lock),避免全表间隙锁
无索引的范围查询会触发表级间隙锁mysql fetch into 详解MySQL InnoDB间隙锁(Gap Lock),必须为查询字段添加索引:
-- 表t:添加name字段的普通索引
ALTER TABLE t ADD INDEX idx_name (name);
-- 范围查询name,仅锁定对应间隙,而非全表
SELECT * FROM t WHERE name LIKE 'z%' FOR UPDATE;
(3)控制事务大小,缩短锁持有时间
长事务会长时间持有间隙锁,导致其他事务阻塞,需简化事务逻辑:
-- 避免:事务内包含非数据库操作(如RPC调用、文件读写)
BEGIN;
SELECT * FROM t WHERE id>2 AND id2 AND id<6 FOR UPDATE;
UPDATE t SET name='a' WHERE id=3;
COMMIT;
-- 后续执行RPC调用(无锁)
五、总结间隙锁是在RR隔离级别下为解决幻读 引入的锁机制,锁定的是索引记录之间的间隙,而非具体行;Next-Key Lock是行锁+间隙锁的组合,是默认的锁定方式,范围查询会触发,等值查询(记录存在)会降级为行锁;间隙锁仅对索引字段 生效,无索引时会触发表级间隙锁,导致锁表;优化间隙锁的核心:优先使用唯一索引等值查询、添加索引、降低隔离级别(RC)、缩短事务时长;间隙锁虽能保证数据一致性,但会降低并发性能,需根据业务场景(是否容忍幻读)选择是否关闭。

1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299
资源库 - 资源分享下载网 » mysql fetch into 详解MySQL InnoDB间隙锁(Gap Lock)
常见问题FAQ
- 关于资源售价和售后服务的说明?
- 代码有没有售后服务和技术支持?
- 有没有搭建服务?
- 链接地址失效了怎么办?
- 关于解压密码

