You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

InnoDB为何在唯一索引唯一查询条件下使用间隙锁?

问题场景与解答

数据表结构

CREATE TABLE `bar` (
  `id` int(11) NOT NULL,
  `age` int(11) NOT NULL,
  `value` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

现有数据

id|age|value|
--+---+-----+
 1|  1|    1|
 5|  5|    5|
 9|  9|    9|

操作流程

  • 连接1执行:
start transaction;
update bar set value = 0 where id = 8;
  • 连接2执行:
start transaction;
insert into bar(id,age,value) values(7,7,7);

此时连接2的插入操作被间隙锁阻塞,锁信息如下:

lock_id    |lock_trx_id|lock_mode|lock_type|lock_table |lock_index|lock_space|lock_page|lock_rec|lock_data|
-----------+-----------+---------+---------+-----------+----------+----------+---------+--------+---------+
5218:85:3:4|5218       |X,GAP    |RECORD   |`bar`.`bar`|PRIMARY   |        85|        3|       4|9        |
5217:85:3:4|5217       |X,GAP    |RECORD   |`bar`.`bar`|PRIMARY   |        85|        3|       4|9        |

核心疑问

根据官方文档说明:

UPDATE ... WHERE ...会对搜索到的每条记录设置排他临键锁。但使用唯一索引查询唯一行的语句仅需索引记录锁

问:是否仅在找到并锁定记录时才使用索引记录锁,否则仍需使用临键锁?


是的,你的理解完全正确。

当使用唯一索引查询唯一行时,只有在找到匹配的记录时,InnoDB才会使用索引记录锁(Record Lock)——仅锁定该条具体的索引记录,不会额外添加间隙锁或临键锁。

但如果查询的唯一索引值不存在对应记录,InnoDB无法定位到具体行,此时会退化为添加间隙锁(GAP Lock)(临键锁本质是记录锁+间隙锁的组合),防止其他事务插入该间隙内的数据,避免幻读问题。

回到你的场景:连接1执行update bar set value = 0 where id = 8时,id作为主键(唯一索引)不存在对应记录,InnoDB会定位到id=5与id=9之间的间隙,并对该间隙添加X类型的间隙锁,这直接导致连接2插入id=7时被阻塞,与你看到的X,GAP锁信息完全吻合。

内容的提问来源于stack exchange,提问作者Tim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 19:06:28