查 Seconds_Behind_Master
是最直接但不够可靠的方式
MySQL 主从复制延迟最常看的指标是
SHOW SLAVE STATUS输出里的
Seconds_Behind_Master字段。它表示从库 SQL 线程落后主库多少秒,但这个值在很多场景下会显示
NULL或
0即使实际有延迟——比如 IO 线程已断、SQL 线程被阻塞但还没报错、或启用了并行复制(
slave_parallel_type = LOGICAL_CLOCK)时计算逻辑不准确。
真正可用的判断逻辑应组合多个字段:
Slave_IO_Running和
Slave_SQL_Running必须都为
Yes
Seconds_Behind_Master> 阈值(如 60 秒)且不为
NULL若为
NULL,进一步检查
Relay_Log_File和
Master_Log_File是否长时间未更新(对比
Relay_Log_Pos和
Read_Master_Log_Pos是否停滞)
用 pt-heartbeat
实现高精度延迟测量
pt-heartbeat是 Percona Toolkit 中专为复制延迟设计的工具,原理是在主库定时写入带时间戳的心跳记录,从库读取并计算差值。它不依赖 MySQL 自身状态,能真实反映端到端延迟,尤其适合跨机房、大事务、GTID 环境。
部署要点:
主库上建专用心跳表:CREATE TABLE percona.heartbeat ( ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, file VARCHAR(255) DEFAULT NULL, position BIGINT UNSIGNED DEFAULT NULL, server_id INTEGER UNSIGNED DEFAULT NULL ) ENGINE=InnoDB;启动守护进程:
pt-heartbeat --daemonize --update --user=root --password=xxx --host=master-host --interval=1从库上轮询检查:
pt-heartbeat --monitor --user=root --password=xxx --host=slave-host --master-server-id=1 --interval=5
注意:
--master-server-id必须指定主库的
server_id,否则可能误读其他主节点的心跳;表必须使用
InnoDB引擎,避免 MyISAM 表锁干扰。
用 Prometheus + mysqld_exporter 做延迟可视化与告警
单纯脚本轮询难持续跟踪趋势,推荐接入 Prometheus 生态。mysqld_exporter 默认采集
mysql_slave_status_seconds_behind_master指标,但该指标本质仍是
Seconds_Behind_Master的直译,不可单独用于告警。
更稳妥的做法是:用
mysqld_exporter的自定义查询功能,把
pt-heartbeat的结果暴露为指标: 在从库上创建视图:
CREATE VIEW heartbeat_delay AS SELECT UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(ts) AS delay FROM percona.heartbeat ORDER BY ts DESC LIMIT 1;配置
mysqld_exporter的
custom_queries.yaml,添加查询:
- metrics: - heartbeat_delay: "delay" request: "SELECT delay FROM heartbeat_delay"Prometheus 告警规则示例:
groups:
- name: mysql_replication_alerts
rules:
- alert: MySQLReplicaHighDelay
expr: mysql_custom_heartbeat_delay > 120
for: 5m
labels:
severity: warning
避免只监控单一维度导致漏告
线上出问题时,延迟往往不是孤立发生的。比如主库 CPU 打满 → binlog 写入变慢 → 从库 IO 线程追不上 →
Seconds_Behind_Master上升;又或者从库磁盘 I/O 延迟高 → SQL 线程执行慢 →
pt-heartbeat显示延迟,但
Seconds_Behind_Master仍为 0(因为 SQL 线程没卡死,只是跑得慢)。
所以真实可用的告警策略必须交叉验证:
同时满足:mysql_slave_status_seconds_behind_master > 300且
mysql_custom_heartbeat_delay > 300→ 确认是真延迟 单独触发
mysql_slave_status_seconds_behind_master == 0但
mysql_slave_status_slave_io_running == 0→ 优先告警 IO 断连 若
mysql_info_schema_innodb_row_lock_time_avg突增,且延迟同步出现,大概率是大事务或锁冲突导致 SQL 线程卡住
延迟数值本身不是关键,关键在于它是否持续、是否伴随其他异常信号。没有上下文的单点阈值告警,90% 会变成噪音。
