Seconds_Behind_Master不准,因其仅反映SQL线程与relay log末事件的时间差,不包含网络延迟、大事务阻塞、时钟不同步、IO断连或并行复制下worker实际进度等真实延迟;真实延迟需结合GTID差集、位点差(Read_Master_Log_Pos与Exec_Master_Log_Pos)、Slave_SQL_Running_State及pt-heartbeat心跳检测综合判断。

Seconds_Behind_Master 高,不能只盯着这个值调参或重启复制 —— 它可能完全失真,而真正卡住同步的,往往是一条没提交的 UPDATE 或一个被锁住的事务。
Seconds_Behind_Master 为什么不准,怎么看真实延迟?
这个值在 MySQL 5.7+ 多数情况下可参考,但遇到以下情况会严重误导:
- 并行复制开启时(
slave_parallel_workers > 0),它只反映 coordinator 线程的“感知延迟”,不体现 worker 实际执行进度 - SQL 线程卡在锁等待(如
Waiting for dependent transaction to commit),Seconds_Behind_Master可能长期显示为0,但Exec_Master_Log_Pos停滞不动 - 主库 binlog 被清理(
expire_logs_days = 1),从库还没来得及消费,Seconds_Behind_Master会变NULL,此时已无法自动恢复
更可靠的做法是三者比对:
- 主库执行
SHOW MASTER STATUS,记下File和Position - 从库执行
SHOW SLAVE STATUS\G,取Relay_Master_Log_File和Exec_Master_Log_Pos - 若两者差值持续扩大(比如 > 100MB),说明 relay log 在堆积,SQL 线程根本没跟上
- 用
SELECT MASTER_POS_WAIT('mysql-bin.000001', 123456789, 10)主动验证某位置是否已同步(注意超时设为合理值,避免阻塞)
SQL 线程卡在 executing,怎么快速定位阻塞语句?
别只看 Seconds_Behind_Master 数字,直接查线程状态:
- 执行
SHOW PROCESSLIST,找到User为system user、Command为Connect的那行,看它的State - 如果长期是
executing+ 一条具体 SQL(比如ALTER TABLE t ADD COLUMN x INT),这就是根因 —— DDL 在从库也是长事务 - 如果是
Waiting for table metadata lock,说明有长查询或未提交事务占着表,需杀掉对应线程(KILL <pid></pid>) - 如果是
Updating且Info显示UPDATE ... WHERE create_time ,大概率没走索引,正在全表扫描锁行
配合 SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED LIMIT 1 查最老事务,确认是否业务方漏了 COMMIT。
开了并行复制还是慢,slave_parallel_type 该怎么选?
MySQL 5.7+ 默认 slave_parallel_type = DATABASE,但只对跨库写入有效;单库多表场景几乎无效。必须切到 LOGICAL_CLOCK:
- 先停复制:
STOP SLAVE - 设类型:
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK' - 设工作线程数:
SET GLOBAL slave_parallel_workers = 4(建议设为 CPU 核数的 75%,不超过 8) - 再启复制:
START SLAVE
注意:改完要立刻查 SHOW PROCESSLIST,确认出现多个 system user 线程(worker),且 State 不全是 Waiting for an event from Coordinator —— 后者说明 coordinator 分发不过来,可能是 relay log 解析瓶颈或磁盘 IO 不足。
大事务拆分后延迟还是降不下来,下一步盯什么?
拆事务只是起点,真正拖慢从库的常是隐性开销:
-
relay_log_space_limit设太小(如默认 0 或仅 1GB),中继日志频繁轮转,触发 IO 阻塞 —— 建议设为 10GB 以上,并监控Relay_Log_Space是否持续逼近该值 - 从库
innodb_flush_log_at_trx_commit = 1+sync_binlog = 1(“双1”),每事务刷盘两次,IO 压力翻倍 —— 追延迟期间可临时设为2和0,追平后再切回 - 主库
binlog_format = STATEMENT,某些函数(如NOW()、UUID())导致从库执行结果不一致,SQL 线程反复重试 —— 统一改ROW - 从库没开
read_only = 1,被误写入脏数据,触发唯一键冲突或主键重复,SQL 线程 stop —— 检查Slave_SQL_Running_State是否含error关键字
最容易被跳过的点:延迟高时,第一反应不是查 SQL 线程状态,而是去 ping 网络、看磁盘 IO —— 其实 80% 的案例里,SHOW PROCESSLIST 里那条 executing 的语句,就是答案。


















