mysqld_exporter采集不到seconds_behind_master是因为mysql从库show slave status返回的该字段本身为null或0,常见于io线程停止、gtid+并行复制、系统时间不同步或mysql版本过低;应改用pt-heartbeat心跳表指标mysql_slave_heartbeat_delay_seconds实现可靠延迟监控。

mysqld_exporter采集不到Seconds_Behind_Master怎么办
直接看现象:mysql_slave_status_seconds_behind_master 指标为 0 或 NaN,甚至整个指标压根不出现——这不是 exporter 崩了,而是它根本没拿到有效值。根本原因是 MySQL 从库上执行 SHOW SLAVE STATUS 返回的 Seconds_Behind_Master 字段本身为 NULL 或 0,常见于以下情况:
-
Slave_IO_Running: No:IO 线程断了,连 relay log 都没在收,延迟自然无法计算 - GTID 模式开启且
slave_parallel_workers > 0:MySQL 内部不维护该字段,强制返回NULL - 主从系统时间不同步:导致时间差计算异常,指标被 exporter 主动跳过
- MySQL 版本低于 5.6.1:该字段未引入,mysqld_exporter 读不到
验证方法:手动登录从库执行 SHOW SLAVE STATUS\G,看输出里 Seconds_Behind_Master 是否真实存在且非 NULL。如果它本身就是空的,Prometheus 再怎么抓也抓不出数字。
为什么不能直接用mysql_slave_status_seconds_behind_master配告警
这个指标名字很唬人,但它是 MySQL 原生字段的直译,继承了所有缺陷。拿它设阈值(比如 > 60)告警,等于把“已失效的仪表盘”当真表用。真正的问题在于:
- 它只反映 SQL 线程和 relay log 最后事件的时间差,不包含网络传输、磁盘刷写、大事务阻塞等真实延迟
- 当 IO 线程中断时,它常为
NULL,而 Prometheus 默认忽略NULL,导致告警静默失效 - 在并行复制或 GTID 模式下,它长期为 0,但实际延迟可能已达数分钟
所以生产环境必须绕过它,用更可靠的替代方案——比如基于心跳表的 mysql_slave_heartbeat_delay_seconds,这才是能落地的延迟指标。
怎样配置pt-heartbeat或自定义查询暴露真实延迟
推荐优先用 pt-heartbeat:它在主库持续写入时间戳,从库实时比对,结果稳定、不受 MySQL 复制机制影响。配置要点:
- 主库创建心跳表:
CREATE TABLE monitor.heartbeat (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) - 主库启动守护进程:
pt-heartbeat --daemonize --update --user=monitor --password=xxx --host=127.0.0.1 - 从库配置 mysqld_exporter 的
queries.yaml,添加自定义查询:
slave_heartbeat_delay: query: "SELECT UNIX_TIMESTAMP() - UNIX_TIMESTAMP(ts) FROM monitor.heartbeat" metrics: - mysql_slave_heartbeat_delay_seconds: "gauge"
然后在 mysqld_exporter 启动时加参数:--config.query-path=queries.yaml。注意确保监控账号对 monitor.heartbeat 有 SELECT 权限。
Grafana 告警规则里如何避免瞬时抖动误报
真实环境中,几秒延迟是常态。用单点值告警,每天都会被批量导入、统计任务触发。必须加时间窗口过滤:
- 用
avg_over_time(mysql_slave_heartbeat_delay_seconds[5m])替代原始指标,平滑掉毛刺 - 叠加状态判断:只在
mysql_slave_status_sql_running == 1 and mysql_slave_status_io_running == 1时才参与计算,避免线程挂了还算延迟 - 阈值建议分层:> 60s 持续 5 分钟触发 P2 告警,> 300s 持续 2 分钟升为 P1,留出人工响应缓冲
最易被忽略的一点:mysql_slave_status_io_running 和 mysql_slave_status_sql_running 这两个布尔指标,本质是整数 0/1,不是字符串 "Yes"/"No"——PromQL 里写成 == "Yes" 会永远不匹配。











