MySQL 唯一索引与锁等待:范围查询导致阻塞
MySQL 唯一索引与锁等待:范围查询导致阻塞
本文将通过一个示例分析 MySQL 唯一索引与锁等待之间的关系,并解释为何即使是唯一索引,如果查询条件包含了范围条件,也会导致锁等待。
表结构如下:
create table t
(
id int not null
primary key,
c int null,
d int null
);
create index c
on t (c);
insert into t values(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25);
MySQL 版本:8.0.32 隔离级别 RR
场景:
假设有两个事务 session A 和 session B,执行以下操作:
| session A | session B | |---|---| | begin; | | | select * from t where id>=15 and id<=20 order by id desc for update ; | | | insert into t values (22,22,22); // 会被阻塞 | | | commit; | |
问题:
由于 id 是主键,session B 为什么会进入锁等待?
解释:
虽然 id 是主键,但是 session A 在查询时使用了范围条件 id>=15 and id<=20,导致查询结果包含了 id=20 的行。由于使用了 for update 语句,session A 对 id=20 行加上了排他锁。
而 session B 在插入新行时,要插入 id=22,比 id=20 大,因此需要等待 session A 事务提交后释放锁才能继续执行。
结论:
即使是唯一索引,如果查询条件中包含了范围条件,也会涉及到锁等待。这是因为范围查询会导致锁定多个行,而不是仅仅锁定单个行。
为了避免锁等待,建议尽量使用精确匹配条件进行查询,或者使用其他方法,例如使用间隙锁,来减少锁冲突。
原文地址: https://www.cveoy.top/t/topic/ntKb 著作权归作者所有。请勿转载和采集!