最可靠的方式是组合监控Seconds_Behind_Master、IO/SQL线程状态及pt-heartbeat端到端延迟,并通过Prometheus交叉验证多维度指标,避免单一阈值误告。

查 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% 会变成噪音。










