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

为何SELECT ... FOR SHARE未被其他事务的UPDATE阻塞?场景解析

问题解答

这是InnoDB基于索引加锁的特性导致的,核心原因在于覆盖索引查询无需回表,不会触及被排他锁占用的聚簇索引行,具体拆解如下:

1. Session1的Update操作加锁情况

当Session1执行update table0 set coAttr0_0=2;时,InnoDB会完成以下加锁动作:

  • 找到聚簇索引(主键pkAttr0对应的索引)中的目标行,给该行加排他锁(X锁);
  • 由于修改的coAttr0_0字段存在于二级索引table0index_commAttr0中,会同步给该二级索引的对应记录加X锁;
  • 二级索引table0index_pk仅包含pkAttr0字段,本次修改不涉及该索引的内容,因此这个索引上的记录不会被加X锁。

2. Session2两次FOR SHARE查询的差异

第一次查询:select pkAttr0 from table0 for share;

这个查询属于覆盖索引查询:MySQL可以直接通过二级索引table0index_pk获取到pkAttr0的值,完全不需要回表访问聚簇索引的行。
由于table0index_pk上的记录没有被Session1加X锁,Session2可以顺利给这个索引的记录加共享锁(S锁),因此不会被阻塞。

第二次查询:select * from table0 for share;

这个查询需要获取所有字段,必须回表访问聚簇索引的行。而Session1已经给聚簇索引的目标行加了X锁,S锁与X锁互斥,因此Session2的查询会被阻塞,直到Session1提交或回滚释放锁。

补充:如果没有手动创建table0index_pk这个二级索引,优化器会直接使用主键索引执行查询,此时当前读会触及被加X锁的聚簇索引行,查询就会被阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:12:49