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

MySQL单索引列范围锁定读为何锁定全部索引记录?

MySQL锁定读的锁范围差异问题分析

一、测试环境搭建

先创建两张对比表并插入测试数据:

create table t1(id integer primary key);
create table t2(id integer primary key, num integer);
insert into t1 values (0),(3),(6),(9);
insert into t2 values (0, 0), (3, 3), (6, 6), (9, 9);

二、事务tx1的锁定读操作与锁状态

开启事务tx1,对表t1执行锁定读:

start transaction;
select * from t1 where id >=3 and id < 8 for update;

此时tx1持有的锁情况如下:
tx1的锁状态

三、事务tx2的锁定读操作与锁状态

回滚tx1后,开启事务tx2,对表t2执行相同条件的锁定读:

start transaction;
select * from t2 where id >=3 and id < 8 for update;

tx2持有的锁情况如下:
tx2的锁状态

tx2的锁范围符合对MySQL锁定模型的认知,但**tx1为何会锁定t1表的全部索引记录?**


更新1:执行计划的差异

通过explain命令查看两张表的执行计划,发现明显差异:
执行计划对比


更新2:数据变更后的执行计划与锁范围变化

正如Bill Karwin的回答所述,执行计划中的type: index表示会扫描整个索引树(可参考MySQL官方文档中关于join types的说明)。但当向t1表插入一行数据insert into t1 values (12)后,执行计划的type变为range,此时再执行相同条件的锁定读,tx1不再锁定全部索引记录:
插入数据后的执行计划

推测该现象是MySQL源码内部的特性导致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 09:53:02