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

MySQL InnoDB加锁读关联表时未选取关联列是否会锁定关联行

结论

SELECT 子句指定返回的列完全不会影响 FOR UPDATE 的加锁范围,你给出的关联查询语句依然会对匹配条件的父表行加锁。


原理说明

你对官方文档的第三种解读是正确的:「结果集准入条件」仅指代 JOIN ON、WHERE、HAVING 等过滤规则,和 SELECT 子句选择哪些列没有任何关系,原因如下:

  • MySQL的查询执行顺序为:FROM/JOIN 表加载 → WHERE 条件过滤 → SELECT 列裁剪 → 其他后续处理,而行锁是在扫描、过滤行的阶段就已经加上,远早于SELECT列的裁剪步骤,后续是否返回父表列完全不会影响前面的加锁逻辑。
  • 你的查询执行过程中,会先扫描匹配到符合Parent.id = ?的父表行、符合Child.id = ?的子表行,再校验JOIN关联条件,所有满足过滤和关联条件的行都属于符合结果集准入条件的行,不会被提前释放锁,和是否在SELECT中返回无关。

验证方式

你可以通过简单的并发测试确认加锁行为:

  1. 开启会话1,执行你给出的关联查询语句,执行后不提交事务
  2. 开启会话2,执行针对对应父表ID的加锁查询SELECT * FROM Parent WHERE id = ? FOR UPDATE
  3. 可以观察到会话2的查询会进入阻塞状态,即可证明会话1已经给对应的父表行加上了排他锁。

优化建议

如果你的场景只需要校验父子路径合法性、不需要读取父表的其他字段,同时不想给父表行加锁,可以直接简化查询语句,利用外键约束的特性(子表的parent_id如果存在关联值,必然对应存在父表行),改写为仅查子表的语句,锁范围更小、执行效率更高:

SELECT Child.*
FROM Child
WHERE Child.parent_id = ? AND Child.id = ?
FOR UPDATE

该语句只会给匹配到的子表行加排他锁,不会触发父表的加锁逻辑。


内容的提问来源于stack exchange,提问作者R. Agnese

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 15:57:02