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

MySQL 8.0中MDL SHARED_READ锁引发死锁的原因是什么?

为什么MySQL 8.0中先通过SELECT获取MDL SHARED_READ锁后执行INSERT会触发死锁?

核心逻辑:MDL锁升级规则+循环等待触发死锁

要理清这个问题,先明确MySQL元数据锁(MDL)的关键类型及兼容性:

  • MDL_SHARED_READ:由普通SELECT触发,允许当前会话读操作,也允许其他会话获取SHARED_READ/SHARED_WRITE锁,但会阻塞MDL_EXCLUSIVE锁(如ALTER TABLE这类DDL操作)
  • MDL_SHARED_WRITE:由INSERT/UPDATE/DELETE触发,允许当前会话读写操作,同样阻塞MDL_EXCLUSIVE锁,且与其他SHARED_READ/SHARED_WRITE锁兼容
  • MDL_EXCLUSIVE:由DDL操作触发,需要独占元数据锁,会阻塞所有其他类型的MDL锁

场景一的死锁形成链条

  1. Session 1开启事务,执行select * from account,获取MDL_SHARED_READ锁
  2. Session 2执行alter table account add columnA int,请求MDL_EXCLUSIVE锁,由于Session 1持有SHARED_READ锁,Session 2进入等待队列
  3. Session 1此时执行INSERT操作,需要将自身持有的MDL_SHARED_READ升级为MDL_SHARED_WRITE锁,但MySQL的MDL锁等待队列遵循**FIFO(先进先出)**规则,升级请求会排在Session 2已提交的EXCLUSIVE锁请求之后,因此Session 1被阻塞
  4. 此时形成循环等待:Session 1等待Session 2的EXCLUSIVE锁释放,Session 2等待Session 1的SHARED_READ锁释放,触发MySQL死锁检测机制,最终回滚Session 1的事务

场景二无死锁的原因

  1. Session 1开启事务,执行insert into account values ('test'),直接获取MDL_SHARED_WRITE锁
  2. Session 2执行ALTER TABLE请求EXCLUSIVE锁,进入等待队列
  3. Session 1后续执行INSERT或SELECT操作,不需要升级MDL锁(SHARED_WRITE已兼容读写操作),因此不会产生新的锁等待请求,自然不会形成循环等待,操作可正常执行

关键细节

MySQL 8.0中MDL锁的升级请求不会插队,必须排在已有的等待锁请求之后,这是场景一死锁的核心触发点。如果先持有SHARED_WRITE锁,后续操作无需升级锁,就不会触发等待链。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:52:28