必须关注replica_io_running、replica_sql_running、seconds_behind_source、replica_io_state、retrieved_gtid_set与executed_gtid_set等关键字段,结合pt-heartbeat验证真实延迟,避免仅凭seconds_behind_source=0误判;监控脚本需适配字段名变更、防元数据锁争抢、校验连接有效性,并用即时通讯工具发送带完整上下文的告警。

怎么看 SHOW REPLICA STATUS 才不算白看
MySQL 8.0.22+ 已弃用 SHOW SLAVE STATUS,必须用 SHOW REPLICA STATUS\G——不是语法糖,是强制升级。只扫一眼 Seconds_Behind_Master: 0 就放心?大概率掉坑里了。
-
Slave_IO_Running和Slave_SQL_Running在新版本中已改为Replica_IO_Running和Replica_SQL_Running,值仍为Yes/No,但字段名变了,脚本不改会解析失败 -
Seconds_Behind_Master在新版本中叫Seconds_Behind_Source,值为NULL不代表“很快”,往往意味着 SQL 线程刚启动、被 kill、或卡在 DDL 锁上没推进 - 真正危险的是
Replica_IO_State: Connecting—— 看似线程在跑,实则连不上主库,超时前一直显示Yes,Seconds_Behind_Source却不动,容易误判 - 启用了 GTID?别漏看
Retrieved_Gtid_Set和Executed_Gtid_Set,差集不为零,说明事务没执行完,哪怕Seconds_Behind_Source是 0
写监控脚本时最常踩的三个坑
用 shell 或 Python 轮询 SHOW REPLICA STATUS 很快,但线上一跑就出事:告警乱发、从库变慢、甚至自己挂掉。
- 高频查状态会争抢元数据锁,尤其 MySQL 8.0+ 默认开一堆 performance_schema 监控项,
crontab每分钟一次看似安全,实际可能堆积连接;建议用sleep 15配合循环,把间隔压到 20–30 秒级,比死守 “每分钟” 更稳 - 别直接
grep "Seconds_Behind_Source:" | awk '{print $2}'——字段顺序可能因 MySQL 版本/字符集微调而偏移;改用mysql -Nse "SELECT Seconds_Behind_Source, Replica_IO_Running, Replica_SQL_Running, Last_IO_Errno, Last_SQL_Errno FROM performance_schema.replication_connection_status JOIN performance_schema.replication_applier_status USING (CHANNEL_NAME)"(需权限),更可靠 - 脚本开头不加
SELECT CONNECTION_ID()校验连接有效性,一旦监控账号密码过期或被 revoke,脚本会把“连不上数据库”当成“复制中断”,天天发告警
延迟报警不能只盯 Seconds_Behind_Source
这个值本质是“SQL 线程当前执行位置”和“IO 线程最新拉到的位置”之间的时间差,它不反映真实业务延迟,更不反映 IO 是否假连。
- 推荐组合使用:
pt-heartbeat写心跳表(主库每秒 insert 时间戳,从库 select 计算差值),结果不受并行复制、GTID 切换、SQL 线程阻塞影响,才是端到端真实延迟 -
Relay_Log_Space持续上涨且Seconds_Behind_Source为 0?说明 SQL 线程根本没开始回放,可能卡在唯一键冲突、ALTER TABLE锁表、或被KILL住但未退出 - 用 Prometheus 监控时,别只设
mysql_replica_status_seconds_behind_source > 120告警;要加条件:持续 2 分钟以上,且mysql_replica_status_replica_io_running == 0 OR mysql_replica_status_replica_sql_running == 0,避免瞬时抖动误报
为什么邮件告警在生产环境基本等于没告
不是邮件不好,是它太慢、太不可靠:DNS 解析失败、MTA 队列积压、进垃圾箱、没人实时看——等你收到,故障可能已扩散。
- 优先走钉钉/企业微信机器人 Webhook,用
curl -X POST -H 'Content-Type: application/json' -d '{"msgtype":"text","text":{"content":"复制异常:IO stopped, error: 2003"}}' https://oapi.dingtalk.com/...,500ms 内触达 - 告警内容必须带上下文:不只是“复制断了”,而是“
Replica_IO_Running: No,Last_IO_Error: error connecting to master 'repl@192.168.5.10:3306',Last_IO_Errno: 2003”,省去登录查日志的中间步骤 - 所有告警必须落本地日志(如
/var/log/mysql-replica-alert.log),格式含时间戳+完整SHOW REPLICA STATUS输出片段,方便事后回溯;别依赖告警渠道本身留痕
真正难的不是发现复制停了,而是识别“看似在跑,其实早断了”或“SQL 线程活着,但一条语句都执行不了”的静默故障。字段含义、工具边界、告警上下文,三者缺一不可。











