MySQL执行Insert时为何常遇死锁?间隙锁GapLock在流程中如何触发?

2026-04-30 11:001阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1153个文字,预计阅读时间需要5分钟。

MySQL执行Insert时为何常遇死锁?间隙锁GapLock在流程中如何触发?

在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 直接抢同一个间隙。

阅读全文
标签:Mysql

本文共计1153个文字,预计阅读时间需要5分钟。

MySQL执行Insert时为何常遇死锁?间隙锁GapLock在流程中如何触发?

在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 直接抢同一个间隙。

阅读全文
标签:Mysql