seconds_behind_master不能单独设阈值告警,必须结合slave_io_running、slave_sql_running状态及relay log位点变化或pt-heartbeat心跳延迟综合判断,否则易漏报误报。

Seconds_Behind_Master 不能直接设阈值告警
它只是 MySQL 估算的逻辑延迟,不是真实端到端耗时。常见失效场景包括:Slave_IO_Running为No时该值仍可能显示0或旧值;启用slave_parallel_type = LOGICAL_CLOCK后计算偏差大;SQL 线程卡在大事务里(如ALTER TABLE)但该字段没更新;从库刚重启时值为NULL。单独用它设阈值会漏报或误报。
必须组合判断的三个状态字段
真正可用的告警逻辑至少要同时满足以下条件:
-
Slave_IO_Running和Slave_SQL_Running都必须是Yes -
Seconds_Behind_Master是数字(非NULL),且大于阈值(如60) - 若为
NULL,需进一步检查:Relay_Log_Pos和Read_Master_Log_Pos在 30 秒内是否无变化
Shell 脚本中典型判断写法:
DELAY=$(mysql -u$USER -p$PASS -e "SHOW SLAVE STATUS\G" | grep "Seconds_Behind_Master" | awk '{print $2}')
IO_STATUS=$(mysql -u$USER -p$PASS -e "SHOW SLAVE STATUS\G" | grep "Slave_IO_Running" | awk '{print $2}')
SQL_STATUS=$(mysql -u$USER -p$PASS -e "SHOW SLAVE STATUS\G" | grep "Slave_SQL_Running" | awk '{print $2}')
<p>if [[ "$IO_STATUS" != "Yes" || "$SQL_STATUS" != "Yes" ]]; then
echo "CRITICAL: replication thread down"
elif [[ "$DELAY" =~ ^[0-9]+$ ]] && [ "$DELAY" -gt 60 ]; then
echo "ALERT: delay $DELAY seconds"
elif [[ "$DELAY" == "NULL" ]]; then</p><h1>追加 relay log 位置停滞检测</h1>
用 pt-heartbeat 替代单点阈值
pt-heartbeat不依赖 MySQL 内部状态,主库定时写心跳记录,从库读取并计算真实延迟,适合跨机房、GTID、大事务等复杂场景。
- 主库建表必须用
InnoDB引擎:CREATE TABLE percona.heartbeat (ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, file VARCHAR(255), position BIGINT UNSIGNED, server_id INTEGER UNSIGNED) ENGINE=InnoDB - 主库启动:执行
pt-heartbeat --daemonize --update --user=root --password=xxx --host=master-host --interval=1 - 从库检查:执行
pt-heartbeat --check --user=root --password=xxx --host=slave-host --master-server-id=1,注意--master-server-id必须准确指定主库 ID
Prometheus 告警规则要交叉验证
mysqld_exporter 暴露的 mysql_slave_status_seconds_behind_master 本质仍是 Seconds_Behind_Master 的直译,不能单独用于告警。
- 必须搭配
mysql_slave_status_slave_io_running和mysql_slave_status_slave_sql_running同时判断 - 更稳妥的做法是把
pt-heartbeat的输出也接入 Prometheus(例如通过自定义 exporter 或文本文件采集) - 告警持续时间建议设为
for: 2m,避免瞬时抖动触发误报
真实延迟永远藏在 IO/SQL 线程状态、relay log 位点变化、心跳差值三者之间,只盯一个数字等于放弃诊断权。











