最直观但不可靠的延迟指标是Seconds_Behind_Master;真正可靠的是Read_Master_Log_Pos与Exec_Master_Log_Pos的差值;pt-heartbeat因绕过MySQL内部逻辑而更准确。

show slave status 输出里哪些字段直接反映延迟
主从延迟最直观的指标是 Seconds_Behind_Master,但它可能为 NULL 或 0 却仍有真实延迟。原因包括:IO 线程未运行、SQL 线程卡住、GTID 模式下启用 relay_log_recovery=ON 时该值不更新。真正可靠的是对比 Read_Master_Log_Pos(已读取的主库 binlog 位置)和 Exec_Master_Log_Pos(已执行到的主库 binlog 位置),差值越大,积压越严重。
重点关注以下字段组合:
-
Slave_IO_Running: Yes且Slave_SQL_Running: Yes—— 两个线程都正常,延迟才可归因于执行慢或主库写入快 -
Seconds_Behind_Master: NULL+Slave_SQL_Running_State: Waiting for dependent transaction to commit—— 可能是并行复制被依赖事务阻塞(尤其在slave_parallel_type=LOGICAL_CLOCK下) -
Relay_Log_Space持续暴涨 —— SQL 线程消费 Relay Log 速度远低于 IO 线程写入速度,典型执行瓶颈
为什么 show slave status 看不到实时延迟?
Seconds_Behind_Master 是基于主库 binlog event 的 original_commit_timestamp 和当前从库系统时间计算的,前提是主库开启了 binlog_transaction_dependency_tracking=COMMIT_ORDER(默认)且从库启用了基于时间戳的依赖追踪。如果主库 MySQL 版本 master_info_repository=TABLE 和 relay_log_info_repository=TABLE,该值可能长期为 0 或 NULL,失去参考价值。
更稳的办法是用主从时间差辅助判断:
- 在主库执行:
SELECT UNIX_TIMESTAMP(); - 在从库执行:
SELECT UNIX_TIMESTAMP(), @@read_only;(确认只读状态) - 若时间差 > 1 秒,且
Exec_Master_Log_Pos长期不动,大概率 SQL 线程 hang 住
用 pt-heartbeat 查延迟比 show slave status 更准吗?
是的。pt-heartbeat 在主库定时插入带时间戳的记录,从库通过查询该记录的延迟来反推复制 lag,完全绕过 MySQL 内部状态逻辑,不受 GTID、并行复制、binlog 格式影响。它还能输出毫秒级延迟、历史趋势、平均/最大延迟等维度。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
使用前需注意:
- 必须在主库创建专用 heartbeat 表(
CREATE TABLE heartbeat (ts TIMESTAMP NOT NULL PRIMARY KEY)),并确保从库有 SELECT 权限 - 运行命令如:
pt-heartbeat --daemonize --update --user=root --password=xxx --host=master_ip --interval=1(主库写入) - 查延迟时连从库:
pt-heartbeat --monitor --user=root --password=xxx --host=slave_ip --master-server-id=1 --interval=1 - 若
pt-heartbeat显示延迟大但Seconds_Behind_Master=0,基本可断定是 MySQL 自身延迟统计失效,不是真没延迟
除了 show slave status,还有哪些命令能定位延迟根源?
单靠 SHOW SLAVE STATUS 只能看到“有没有延迟”,看不出“为什么延迟”。得配合其他命令交叉验证:
- 查 SQL 线程正在执行什么:
SHOW PROCESSLIST中找User=system user且Command=Query的行,看State是否为Updating、Sorting result或长时间Waiting for table metadata lock - 查 relay log 当前处理位置:
SHOW RELAYLOG EVENTS IN 'relay-bin.000001' FROM 123456789 LIMIT 10;,对比Exec_Master_Log_Pos确认是否卡在某条语句 - 查慢日志是否开启并捕获到复制 SQL:
SELECT @@slow_query_log, @@long_query_time;,再检查从库 slow log 中是否有INSERT/UPDATE执行超时 - 查磁盘 I/O 是否成为瓶颈:
iostat -x 1观察%util和await,特别是 relay log 所在磁盘(常为/var/lib/mysql/)
真正卡住复制的,往往是单条大事务(比如未加 limit 的 delete)、锁等待、或者从库上人为执行了长事务导致元数据锁堆积——这些都不会直接体现在 Seconds_Behind_Master 里,得靠 processlist 和慢日志往下挖。










