真正靠谱的从库延迟判断应对比主从binlog位置,而非仅信seconds_behind_master;需主库show master status与从库relay_master_log_file和exec_master_log_pos比对,或用pt-heartbeat打时间戳。

怎么看从库延迟到底有多大
延迟值不能只信 Seconds_Behind_Master,它在很多场景下是错的:比如主库空闲时从库 IO 线程没活干,这个值会卡在 0;又或者从库 SQL 线程卡住但 IO 线程还在收 binlog,它也可能显示为 0。真正靠谱的是对比主从的 binlog 位置。
实操建议:
- 在主库查:
SHOW MASTER STATUS,记下File和Position - 在从库查:
SHOW SLAVE STATUS\G,重点看Relay_Master_Log_File和Exec_Master_Log_Pos - 如果
Relay_Master_Log_File和主库File不一致,说明 relay log 还没追上主库最新 binlog 文件;即使一致,也要比对Exec_Master_Log_Pos和主库Position差多少字节 - 更稳的做法是用
pt-heartbeat(Percona Toolkit)打时间戳,它能绕过 MySQL 自身状态的误导
为什么 SHOW SLAVE STATUS 里 SQL_Thread_State 总停在 “Reading event from the relay log”
这说明 SQL 线程没卡死,但处理速度跟不上 relay log 的写入速度——本质是单线程回放瓶颈,尤其在主库高并发写入、从库硬件弱或存在大事务时特别明显。
常见诱因和应对:
- 主库批量更新没拆分,一个事务改了 50 万行 → 从库必须等这个事务完全执行完才推进位点;上线前务必检查是否有未加 limit 的
UPDATE/DELETE - 从库
innodb_flush_log_at_trx_commit=1+sync_binlog=1,磁盘 I/O 成瓶颈;若业务允许,可临时调成2和0(注意主从一致性风险) - 从库开了
log_slave_updates又做级联复制,多一层解析开销;非必要不开启 - MySQL 5.7+ 可启用
slave_parallel_workers > 0,但只对LOGICAL_CLOCK并行模式有效,且要求主库binlog_transaction_dependency_tracking=WRITESET
怎么快速定位是哪条语句拖慢了从库回放
直接看 SHOW PROCESSLIST 没用,SQL 线程只显示“system user”,得靠 binlog 解析反推。
操作步骤:
- 先用
mysqlbinlog --base64-output=DECODE-ROWS -v解析从库当前正在执行的 relay log(路径见Relay_Log_File),配合grep -A 10 -B 5 "exec_time"找耗时长的事件 - 重点关注
exec_time大于 10 秒的Query_log_event或Xid_log_event - 如果启用了 ROW 格式,用
mysqlbinlog --verbose --base64-output=DECODE-ROWS加上--start-position精确定位到具体事务,再结合应用日志查对应业务操作 - 别依赖
slow_query_log,从库的慢日志记录的是回放语句,但默认不记录 DML 回放细节,且格式和主库不同
监控脚本里该抓哪些关键指标才不漏报
只轮询 Seconds_Behind_Master 就像只看体温不管血氧,容易误判。真正要进监控系统的字段得组合判断。
必须采集的字段(来自 SHOW SLAVE STATUS):
-
Slave_IO_Running和Slave_SQL_Running:必须都是Yes,否则同步已断 -
Seconds_Behind_Master:阈值设宽些(比如 > 60 秒告警),仅作辅助参考 -
Retrieved_Gtid_Set和Executed_Gtid_Set(GTID 模式下):差集大小反映未执行事务数,比时间更稳定 -
Relay_Log_Space:持续增长且不下降,说明 SQL 线程追不上,relay log 在疯狂堆积
容易被忽略的一点:监控脚本读取 SHOW SLAVE STATUS 时要用 mysql --skip-column-names -e "SHOW SLAVE STATUS\G",否则字段顺序不稳定,解析容易错位。











