答案是:从库sql线程卡住会引发全局mdl等待,因ddl需排他mdl锁,阻塞后所有对该表的读写及ddl操作均卡在“waiting for table metadata lock”状态,必须定位并终止持有锁的源头事务,而非直接kill alter线程。

从库SQL线程卡住会扩散成全局MDL等待
MySQL从库执行DDL(比如 ALTER TABLE)时,SQL线程必须获取表级元数据锁(MDL),而这个锁是排他性的。一旦SQL线程在等锁或执行中被阻塞,后续所有尝试访问同一张表的连接——包括读请求(SELECT)、写请求(INSERT/UPDATE),甚至其他DDL——都会在 Opening tables 阶段卡住,状态统一变成 Waiting for table metadata lock。
这不是“从库慢”,而是锁传播:SQL线程没完成回放 → 表的MDL未释放 → 所有新连接对该表的操作全部排队等待。
- 即使主库上该DDL是online的(如加列、改列类型),从库仍可能卡住,因为从库SQL线程是单线程回放,默认隔离级别为
READ-COMMITTED,优化器行为与主库不同,容易触发全表扫描或锁升级 - 从库上若有长事务未提交(哪怕只是个未
COMMIT的SELECT ... FOR UPDATE),也会让DDL无限期等待,且SHOW PROCESSLIST可能看不到活跃语句,需查information_schema.INNODB_TRX -
performance_schema.events_statements_current有时能暴露“已失败但未释放锁”的隐形事务(例如查询了不存在字段后事务未显式结束)
为什么不能直接KILL掉那个ALTER线程?
直接 KILL 正在执行 ALTER TABLE 的线程,大概率杀的是受害者,不是加害者。真正持有MDL不让步的,往往是另一个未提交事务、一个慢查询、或一个卡在IO上的大事务。
正确做法是定位阻塞源头:
- 查
sys.schema_table_lock_waits视图(MySQL 5.7+):SELECT sql_kill_blocking_connection FROM sys.schema_table_lock_waits WHERE waiting_query LIKE 'alter table%';—— 它返回的KILL xxx命令才是真正该杀的会话ID - 若没有
sys库,手动关联:SELECT * FROM performance_schema.data_lock_waits找出BLOCKING_ENGINE_LOCK_ID,再 JOINdata_locks看锁归属的THREAD_ID和OBJECT_NAME - 别信
State字段里写的altering table—— 它只表示SQL线程当前动作,不反映谁在拦路
从库DDL卡住时,主库操作不受影响,但风险在累积
主库可以照常执行DDL,但从库延迟(Seconds_Behind_Master)会持续上涨。更危险的是:如果从库SQL线程长时间卡在MDL等待中,它不会自动重试或降级;一旦超时(默认 innodb_lock_wait_timeout = 50 秒),它会报 Lock wait timeout exceeded 并中断复制,但MySQL会静默重试最多10次才写入错误日志——你看到的“没报错”,其实是它在后台反复失败。
- 这种重试会持续占用SQL线程,导致后续所有binlog事件积压,延迟不可逆增长
- 如果此时主库又发来另一条涉及同一张表的DDL,从库将陷入嵌套等待,恢复窗口急剧收窄
-
ANALYZE TABLE在从库上对相关表执行,有时能改善执行计划、避免全表扫描型DDL,但无法绕过MDL冲突本身
真正有效的缓解路径只有两条
要么清掉阻塞源(找到并终止持有MDL的事务),要么绕开MDL(不走原生DDL)。没有第三条捷径。
- 清源:优先用
sys.schema_table_lock_waits定位并KILL阻塞方;若不可用,查INNODB_TRX+PROCESSLIST+events_statements_current组合确认“活锁”或“假空闲”事务 - 绕开:对大表结构变更,改用
pt-online-schema-change工具,在从库上也能安全运行(它不依赖SQL线程,而是通过触发器+拷贝+原子切换);注意它会增加磁盘和CPU压力,需提前评估 - 预防:从库禁用
AUTOCOMMIT=FALSE的长事务脚本;监控INNODB_TRX.trx_started超过30分钟的事务;DDL操作前先在从库上SELECT COUNT(*)确认无活跃事务
MDL不是行锁,它不记录在 INNODB_LOCKS 里,也不受 innodb_rollback_on_timeout 影响——这意味着一旦卡住,没人替你自动兜底。











