slave_sql_running_state是sql线程当前执行阶段的快照,非错误标识;常见值如system lock实为等待binlog dump锁、mdl或relay log文件锁等系统级资源,并非操作系统锁,需结合seconds_behind_master持续增长、show processlist及performance_schema.metadata_locks交叉验证是否真卡住。

Slave_SQL_Running_State 不是错误,而是 SQL 线程当前执行阶段的快照;它本身不表示异常,但结合 Seconds_Behind_Master 持续增长或 Slave_SQL_Running = Yes 却无进展,就说明线程卡在某个系统级等待上。
Slave_SQL_Running_State 常见值及真实含义
这个字段反映的是从库 SQL 线程“此刻正在干什么”,不是状态码,不能单看它判断故障,但能帮你定位卡点。常见值包括:
-
Reading event from the relay log:正常态,SQL 线程正从 relay log 读取下一个事件 -
Waiting for table metadata lock:正在等 MDL(metadata lock),通常因为有长事务、DDL 或未提交事务占着表 -
System lock:不是表锁,而是 MySQL 内部需要获取 binlog dump 锁、relay log 文件锁或全局系统锁时被阻塞 -
Waiting for dependent transaction to commit:启用了binlog_order_commits=ON(默认)且事务有依赖关系,当前事务在等上游事务提交 -
Slave has read all relay log; waiting for the slave I/O thread to update it:relay log 已消费完,SQL 线程空闲等待新事件
为什么看到 System lock 就该警惕?
System lock 表面看只是“等待中”,但它背后往往对应不可见的资源争用:
- 主库刚执行完大事务(如
ALTER TABLE),binlog 写入未完全刷盘,从库 SQL 线程在等 binlog dump 锁释放 - 从库自身有未提交事务(哪怕只是
BEGIN; SELECT ...;),会持有一个隐式 MDL,阻塞后续 relay log 中同表的 DML - relay log 文件被其他进程(如备份脚本、logrotate)打开或锁定,SQL 线程无法读取下一段
- MySQL 5.7+ 启用 GTID 后,若从库
gtid_executed和gtid_purged不一致,也可能触发内部锁等待
如何快速确认是不是真卡住?
别只盯着 Slave_SQL_Running_State,要交叉验证:
- 查
Seconds_Behind_Master:持续增长 > 0,且Slave_SQL_Running = Yes→ 很可能卡了 - 查
Last_SQL_Error:为空 ≠ 正常,只是没报错,不代表没卡 - 执行
SHOW PROCESSLIST:找 State 为System lock或Waiting for table metadata lock的线程,看其 Info 是否为空或停在某条 SQL 上 - 查
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA NOT LIKE 'performance_schema';(需开启 performance_schema):确认是否有未释放的 MDL
容易被忽略的关键点
最常被跳过的其实是“从库自己干的事”:
- 从库执行了
FLUSH TABLES WITH READ LOCK或开启了read_only=0并手动写了数据,会导致后续 relay log 中同表操作被锁住 - 从库开了
innodb_lock_wait_timeout但设得太小(比如 1 秒),而主库事务实际要 2 秒才提交,从库 SQL 线程反复超时重试,表现为状态在System lock和Reading event...间跳变 -
relay_log_info_repository = FILE(老默认)时,relay log 位置写入磁盘延迟,可能导致 SQL 线程误判进度,陷入假等待











