必须配告警的MySQL指标有五个:mysql_up!=1(实例宕机)、threads_connected/max_connections>80%(连接数过载)、threads_running/max_connections>60%(活跃线程过高)、rate(slow_queries[5m])>10(慢查询激增)、aborted_connects增量突增(暴力破解或配置错误),它们直接关联业务中断或故障前兆。

哪些 MySQL 指标必须配告警,而不是“可选”
不是所有 SHOW GLOBAL STATUS 返回的指标都值得告警。真正需要触发通知的,是那些一旦异常就大概率已影响业务、或预示故障即将发生的指标。比如 mysql_up 为 0,数据库已经挂了,再不告警就不是监控,是摆设。
-
mysql_up{instance=~".+"}!= 1:这是最基础的存活信号,值为 0 表示 Exporter 连不上 MySQL 或 MySQL 进程已退出 -
mysql_global_status_threads_running{instance=~".+"}>max_connections* 0.8:活跃线程长期超过连接池上限 80%,说明查询堆积或存在长事务阻塞 -
rate(mysql_global_status_slow_queries{instance=~".+"}[5m])> 10:5 分钟内慢查速率持续超 10 次/秒,大概率有未优化 SQL 正在拖垮实例 -
mysql_global_status_aborted_connects{instance=~".+"}增量突增(如 1 分钟内 +50):可能遭遇暴力爆破、配置错误或网络抖动,不是“偶尔失败”,而是批量失败
为什么 innodb_buffer_pool_hit_ratio 不建议直接告警
很多文档把缓冲池命中率当核心指标,但直接对它设阈值(比如 (1 - innodb_buffer_pool_reads / innodb_buffer_pool_read_requests) * 100,而 innodb_buffer_pool_reads 在刚启动或缓存被清空时会短暂飙升,导致命中率瞬间跌到 0 —— 这不是故障,是正常冷启动过程。
更稳妥的做法是监控其变化趋势+绝对值双条件:
- 命中率连续 5 分钟 且
innodb_buffer_pool_read_requests> 10000/分钟:说明真实存在缓存压力 - 避免单独用
rate()计算,因分母为 0 时 Prometheus 会返回NaN,告警规则失效
mysql_slave_status_seconds_behind_master 的坑在哪
这个指标只在从库上存在,且仅当复制线程(IO/SQL)都为 Yes 时才有效。如果 Seconds_Behind_Master 显示 NULL 或 0,不代表复制健康——可能 IO 线程已断、SQL 线程卡死,但指标仍维持旧值甚至不更新。
正确做法是组合判断:
-
mysql_slave_status_slave_io_running{instance=~".+"}== 0 或mysql_slave_status_slave_sql_running{instance=~".+"}== 0:任一为 0 就立即告警 -
mysql_slave_status_seconds_behind_master{instance=~".+"}> 300 且 持续 3 个采集周期:避免瞬时网络抖动误报 - 注意:MySQL 8.0.22+ 使用
replica替代slave,指标名变为mysql_replica_status_...,旧规则会漏监控
告警阈值不能写死,得看场景
同一个指标,在 OLTP 和 OLAP 实例上的合理阈值可能差一个数量级。比如 Threads_running:
- 交易类实例(高并发短事务):> 50 就需告警,CPU 很快打满
- 报表类实例(低频长查询):> 10 就值得警惕,说明大查询没做资源隔离
- 用标签区分:在 Prometheus 中通过
{job="mysql-oltp"}或{env="prod"}动态匹配不同规则,而不是所有实例共用一套阈值
真正难的不是列出指标,而是判断哪个异常代表“现在就得人工介入”。比如 Aborted_clients 突增,可能是连接池配置错误;Innodb_row_lock_waits 每秒涨几十次,说明业务正在发生锁竞争——这些信号背后对应的是具体运维动作,不是数字本身。



















