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持有的锁情况如下:
三、事务tx2的锁定读操作与锁状态
回滚tx1后,开启事务tx2,对表t2执行相同条件的锁定读:
start transaction; select * from t2 where id >=3 and id < 8 for update;
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
相关产品推荐
相关产品推荐

