MySQL执行Insert时为何常遇死锁?间隙锁GapLock在流程中如何触发?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1153个文字,预计阅读时间需要5分钟。
在InnoDB中,`INSERT`语句本身不会直接加间隔锁,但会在插入前检查唯一性、定位插入位置时触发间隔锁。必须确保新记录不会破坏索引顺序或违反唯一约束。因为这将导致在目标位置的前后尝试加锁——如果该间隔锁已被其他事务使用`SELECT ... FOR UPDATE`或`UPDATE`锁定,则当前`INSERT`会阻塞,形成等待链**。
常见现象是:事务 A 执行 SELECT id BETWEEN 10 AND 20 FOR UPDATE,事务 B 紧接着执行 INSERT INTO t VALUES (15, ...),后者卡住不动,SHOW ENGINE INNODB STATUS 显示 “waiting for gap lock”。
- 只有主键或唯一索引列参与插入判断时,才会触发间隙锁(非唯一索引也可能,但逻辑更复杂)
- 无索引字段上的 Insert 不会触发间隙锁,但可能退化为表锁(极危险)
- 即使 Insert 的值在表中“不存在”,只要它落在已被锁定的间隙内,就会被拦住
死锁不是 Insert 和 Insert 之间发生的
死锁通常发生在 **Insert 与范围查询/更新事务的交叉等待** 中,而不是两个 Insert 直接抢同一个间隙。
本文共计1153个文字,预计阅读时间需要5分钟。
在InnoDB中,`INSERT`语句本身不会直接加间隔锁,但会在插入前检查唯一性、定位插入位置时触发间隔锁。必须确保新记录不会破坏索引顺序或违反唯一约束。因为这将导致在目标位置的前后尝试加锁——如果该间隔锁已被其他事务使用`SELECT ... FOR UPDATE`或`UPDATE`锁定,则当前`INSERT`会阻塞,形成等待链**。
常见现象是:事务 A 执行 SELECT id BETWEEN 10 AND 20 FOR UPDATE,事务 B 紧接着执行 INSERT INTO t VALUES (15, ...),后者卡住不动,SHOW ENGINE INNODB STATUS 显示 “waiting for gap lock”。
- 只有主键或唯一索引列参与插入判断时,才会触发间隙锁(非唯一索引也可能,但逻辑更复杂)
- 无索引字段上的 Insert 不会触发间隙锁,但可能退化为表锁(极危险)
- 即使 Insert 的值在表中“不存在”,只要它落在已被锁定的间隙内,就会被拦住
死锁不是 Insert 和 Insert 之间发生的
死锁通常发生在 **Insert 与范围查询/更新事务的交叉等待** 中,而不是两个 Insert 直接抢同一个间隙。

