mysql主从复制中的延迟监控与警报配置

来源:这里教程网 时间:2026-02-28 20:40:01 作者:

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

相关推荐