RSS
菜单
全部文章快讯开发科技深度热点

第 64 章 监控与告警踩坑

内容摘要

监控不是"装个 agent 采几个指标"就完事,告警太多没人看、告警太少出事不知道,都是血泪教训。本篇基于 MySQL 8.0 的常用监控指标与告警体系,梳理监控覆盖、阈值设计、告警闭环、容量预测等 11 个高频坑。前置知识是性能监控与慢查询。学完后你应能搭一套"采得全、报得准、有人接、可追溯"的监控告警体系。

📖 本篇简介:监控不是"装个 agent 采几个指标"就完事,告警太多没人看、告警太少出事不知道,都是血泪教训。本篇基于 MySQL 8.0 的常用监控指标与告警体系,梳理监控覆盖、阈值设计、告警闭环、容量预测等 11 个高频坑。前置知识是性能监控与慢查询。学完后你应能搭一套"采得全、报得准、有人接、可追溯"的监控告警体系。

目录

  • 坑 1:只采 CPU 不采慢查询与锁等待
  • 坑 2:告警阈值拍脑袋设置不合理
  • 坑 3:告警风暴导致无人响应
  • 坑 4:漏掉主从延迟这个关键指标
  • 坑 5:磁盘满告警发现得太晚
  • 坑 6:缺少业务视角的 QPS 监控
  • 坑 7:告警没有升级与值班闭环
  • 坑 8:只看当下不做趋势预测
  • 坑 9:忽略错误日志与告警事件
  • 坑 10:监控 agent 自身占用过多资源
  • 坑 11:告警渠道单一且不可靠
  • 监控大盘设计要点
  • 监控与告警常见注意事项
  • 速查表:MySQL 核心监控指标
  • 自测练习

坑 1:只采 CPU 不采慢查询与锁等待

场景 / 错误示范:

监控大盘只展示 CPU 使用率、内存、磁盘这些 OS 指标。CPU 看着很正常,但业务已经慢得不行——因为是慢 SQL 和行锁等待把数据库拖住了,OS 指标完全看不出来。

-- 错误:监控只看 CPU/内存,从来不看数据库内部状态
-- 业务卡顿时,CPU 可能才 30%,但锁等待队列已经很长

为什么是坑:CPU 正常不代表数据库健康。MySQL 的大量问题(慢 SQL、锁等待、缓冲池命中率低、临时表落盘)都发生在"数据库内部",OS 层指标根本反映不出来。只监控 OS 指标,等于透过门缝看病——能看到的都不是病。真正决定用户体验的是慢查询数、锁等待、QPS 这些数据库内部指标。

正确做法:

OS 指标 + 数据库内部指标一起采,重点是慢查询和锁。

-- 监控核心数据库内部指标(本示例基于 MySQL 8.0)
-- 1) 慢查询数量
SHOW GLOBAL STATUS LIKE 'Slow_queries';
-- 2) 当前正在执行的长事务/锁等待
SELECT * FROM information_schema.INNODB_TRX
ORDER BY trx_started ASC LIMIT 10;
-- 3) 行锁等待次数
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_waits';
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_current_waits';
-- 4) 缓冲池命中率
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';

加分点:慢日志必须开启并采样采集,它是定位"业务为什么慢"的第一手证据。


坑 2:告警阈值拍脑袋设置不合理

场景 / 错误示范:

DBA 凭感觉把 CPU 告警设到 80%。结果业务高峰期 CPU 天天 85%,告警一天响几十次,大家逐渐麻木,真出问题时反而被当成噪音忽略。

# 错误:阈值凭感觉,没有基于历史基线
alerts:
  - cpu_usage: ">80%"    # 高峰期常态 85%,天天告警

为什么是坑:阈值定太高,频繁误报导致"狼来了"效应;定太低,真出问题又发现太晚。合理阈值要基于历史基线——知道正常水位是多少、波动范围多大,才能定出"偏离基线才告警"的标准。拍脑袋设的阈值,要么噪音要么漏报。

正确做法:

基于历史分位数和同比环比设阈值,而非固定死值。

# 正确:基于历史基线动态告警
alerts:
  # 比过去 7 天同一时段 P99 高 50% 才告警,而不是固定 80%
  - cpu_usage: "> P99(7d, same_time) * 1.5"
  # 磁盘容量绝对阈值 + 增长速率双保险
  - disk_usage: ">85%"
  - disk_growth_rate: "> 5GB/小时"

加分点:告警要区分"Warning"和"Critical",Warning 先观察,Critical 才电话轰炸。


坑 3:告警风暴导致无人响应

场景 / 错误示范:

一台主库宕机,瞬间触发 CPU、连接数、主从延迟、业务报错等几十条告警,群里被刷屏。值班同学看不过来,反而不知道先处理哪个,关键问题被淹没。

# 错误:一个故障触发几十条独立告警,无聚合无收敛
[Alert] CPU > 90%
[Alert] 连接数 > 900
[Alert] 主从延迟 > 300s
[Alert] 业务接口 5xx
... 刷屏 50 条

为什么是坑:监控系统如果不对告警做聚合,一个根因会炸出一堆衍生告警。值班人面对满屏告警,反而抓不住主要矛盾。告警风暴的本质问题不是"告警太多",而是"没有把同源告警收敛成一个事件"。

正确做法:

告警收敛聚合,同源告警合并成一个事件。

# 正确:根因告警触发后,自动屏蔽其衍生告警,合并成一个事件
[Event] 主库 10.0.0.11 不可达 (Critical)
  └ 衍生: CPU 飙升 / 连接数耗尽 / 主从延迟 / 接口报错 (自动收敛,不重复告警)

加分点:告警平台支持"告警依赖/抑制规则",主库宕机时自动抑制从库延迟等衍生告警。


坑 4:漏掉主从延迟这个关键指标

场景 / 错误示范:

监控了主库的一切,却没监控主从延迟。业务做读写分离,用户刚下单(写主库),立刻查订单(读从库),从库延迟 5 秒,用户看到"订单不存在",投诉才发现。

-- 错误:从不监控 Seconds_Behind_Source
-- 从库延迟悄悄累积,读写分离下用户读不到刚写的数据

为什么是坑:读写分离架构里,主从延迟直接决定"用户能不能读到自己刚写的数据"。这是业务可见的问题,比 CPU 飙高更影响体验。不监控主从延迟,等于对"读写分离一致性"失明。延迟会随大事务、从库压力波动累积,不监控就发现不了。

正确做法:

把主从延迟作为核心告警指标。

-- 监控主从延迟(本示例基于 MySQL 8.0)
SHOW REPLICA STATUS\G
-- 关键告警字段:
--   Seconds_Behind_Source > 10s  -> Warning
--   Seconds_Behind_Source > 60s  -> Critical
--   Replica_SQL_Running = No     -> 复制中断,立即告警
--   Replica_IO_Running  = No     -> IO 线程断

加分点:更精准的做法是在从库做"主库写心跳表、从库查延迟"的真实业务延迟探测,比 Seconds_Behind_Source 更准。


坑 5:磁盘满告警发现得太晚

场景 / 错误示范:

磁盘用到 95% 才告警,DBA 收到电话时数据库已经因为写不进去而报错。binlog 暴涨把盘占满,数据库直接 hang。

# 错误:只在磁盘快满时才告警,没有水位线提前量
# df 显示 98% 才通知,此时数据库已经无法写入

为什么是坑:磁盘满是数据库致命故障——写不进去、binlog 写不了、甚至实例 crash。等到 95% 才告警,留给 DBA 处理的时间几乎为零。磁盘监控必须有梯度水位线,在还充裕时就预警,而不是等炸了才知道。

正确做法:

分级磁盘水位线,提前预警。

# 正确:多级水位线,越早预警越从容
# 70% -> 通知 DBA 关注
# 80% -> Warning,开始清理/扩容流程
# 85% -> Critical,紧急处理
# 同时监控磁盘增长速率,预测何时打满
-- 同时关注 binlog 占用,及时清理过期 binlog(本示例基于 MySQL 8.0)
SHOW BINARY LOGS;              -- 查看所有 binlog 及大小
PURGE BINARY LOGS BEFORE '2026-10-01 00:00:00';  -- 清理 7 天前的 binlog

加分点:磁盘监控要同时看"容量水位"和"增长速率",后者能提前预测"3 天后打满",比看水位主动得多。


坑 6:缺少业务视角的 QPS 监控

场景 / 错误示范:

监控全是技术指标(CPU、连接数),但没有"这个库每秒扛了多少查询、业务有没有变慢"的视角。某天业务接口变慢,技术指标都正常,查半天才发现是某条慢 SQL 把 QPS 结构拖垮。

-- 错误:不按业务/SQL 维度统计 QPS
-- 出问题时不知道是哪类业务、哪条 SQL 拖慢了整体

为什么是坑:技术指标告诉你"系统现在负载多少",但不告诉你"业务现在还好不好"。没有业务维度的 QPS、RT、错误率监控,就无法第一时间回答"现在用户有没有受影响"。技术监控是手段,业务体验才是目的,两者缺一不可。

正确做法:

监控业务级 QPS、RT、错误率,并按核心 SQL/接口拆分。

-- 按 SQL 维度采集(本示例基于 MySQL 8.0,需开启 performance_schema)
SELECT digest_text, count_star, avg_timer_wait/1e9 AS avg_ms
FROM performance_schema.events_statements_summary_by_digest
ORDER BY count_star DESC LIMIT 20;
-- 看哪类 SQL 调用最多、平均耗时最长,业务视角一目了然

加分点:把"核心接口 RT""订单创建成功率"这类业务指标和数据库指标放在同一张大盘,一眼看清因果。


坑 7:告警没有升级与值班闭环

场景 / 错误示范:

告警发到群里就完事了,没人响应也没有升级。半夜 Critical 告警,值班同学睡着了没看见,第二天早上才发现库挂了一夜。

# 错误:告警只发群消息,无值班、无升级、无人认领
[Alert] 主库不可达
# 无人确认,无人处理,直到第二天业务方投诉

为什么是坑:告警发出去不等于"有人处理"。没有值班排班、没有认领确认、没有超时升级,告警就是单向通知,很容易被淹没或被忽略。监控告警的最后一公里是"人要接上",否则前面采得再全也白搭。

正确做法:

告警必须有"确认-升级-闭环"机制。

# 正确:Critical 告警多渠道触达 + 超时升级
[Critical] 主库不可达
  -> 电话呼叫值班 oncall (0~5 分钟未确认)
  -> 5 分钟未确认,升级到组长 oncall
  -> 10 分钟未确认,升级到技术总监
  -> 处理完成后在告警单上记录根因和处理结果,闭环复盘

加分点:每条 Critical 告警都要在告警系统里留单,事后复盘"从告警到恢复花了多久",持续缩短 MTTR。


坑 8:只看当下不做趋势预测

场景 / 错误示范:

监控都是"当前值是多少",没有趋势。数据库连接数、磁盘、QPS 都在缓慢增长,直到某天突然触顶告警,才发现早就该扩容了。

-- 错误:只看实时指标,不看环比增长
-- 连接数每周涨 5%,3 个月后触顶,事前毫无预警

为什么是坑:很多故障是"渐变"而非"突变"——数据量增长、连接数累积、磁盘膨胀,都是慢慢爬到阈值的。只看实时值,等触顶就晚了。趋势预测能提前几周告诉你"按这个增速,X 周后磁盘满/连接数打满",把被动救火变成主动扩容。

正确做法:

保留足够长的历史数据,做增长趋势预测。

-- 按天采样关键指标,计算周环比增长率(本示例基于 MySQL 8.0 监控库)
-- 示例:连接数
SELECT event_date,
       MAX(Connections) AS max_conn,
       MAX(Connections) - LAG(MAX(Connections)) OVER (ORDER BY event_date) AS wow_growth
FROM db_metrics
GROUP BY event_date
ORDER BY event_date DESC;
-- 据此预测何时触顶 max_connections,提前扩容

加分点:容量规划类告警("预计 20 天后磁盘满")比阈值告警价值高一个量级。


坑 9:忽略错误日志与告警事件

场景 / 错误示范:

监控大盘一片绿,但 MySQL error log 里早就反复出现 Too many connections、Aborted connection,这些前兆没人看,等真正宕机已经晚了。

# 错误:从不采集 MySQL 错误日志
# error log 里的 Aborted connection / 死锁 / 宕机前兆都被无视
tail -f /var/log/mysql/error.log   # 从来没人看

为什么是坑:MySQL 错误日志记录了所有异常事件——死锁、连接 aborted、复制中断、重启前兆。这些是故障的"早期信号",比指标越界更早出现。不采集错误日志,就失去了最直接的故障预警来源。

正确做法:

采集并解析 error log,对关键错误模式告警。

# 采集 MySQL error log,对关键模式告警(本示例基于 MySQL 8.0)
# 关注的错误模式:
#   'Too many connections'      -> 连接数即将打满
#   'Deadlock found'            -> 死锁
#   'Aborted connection'        -> 连接异常断开
#   'replication' / 'IO thread' -> 复制异常
#   'starting' / 'shutdown'     -> 实例异常重启

加分点:error log 解析后按错误类型聚合计数,某类错误突增本身就是告警信号。


坑 10:监控 agent 自身占用过多资源

场景 / 错误示范:

为了监控,在数据库机器上跑了一个重 agent,每秒采集上百个指标,自身 CPU 占用 15%、内存 1G。本来数据库就紧张,监控自己成了负担。

# 错误:采集过于频繁、指标过多,agent 自身开销大
# 每 1 秒采全量 performance_schema,CPU 占用 15%

为什么是坑:监控是为了保障数据库,不能反过来拖垮数据库。采集频率过高、指标过多、查询 performance_schema 太频繁,agent 自己就成了负载。尤其在性能敏感的生产库,监控开销必须控制在很小的比例。

正确做法:

合理控制采集频率和指标范围,把开销降到最低。

# 正确:采集频率适中,只采必要指标
collect:
  interval: 15s          # 不是每秒
  perf_schema: 60s      # performance_schema 重,1 分钟采一次
  slow_log_sample: 采样  # 慢日志只采样,不全量解析

加分点:对延迟不敏感的指标(如容量、版本)甚至可以几分钟采一次,别一刀切高频。


坑 11:告警渠道单一且不可靠

场景 / 错误示范:

告警只发邮件。半夜 Critical 告警,邮件没人看,等早上发现时故障已持续 8 小时。

# 错误:告警只有邮件一个渠道,深夜必然漏看
[Alert] 主库不可达  -> send mail -> 无人查看

为什么是坑:不同级别告警需要不同触达方式。普通 Warning 发群消息即可,Critical 必须电话/短信这种"强打扰"渠道。只靠邮件或群消息,深夜和节假日必然漏接。告警渠道要和告警级别匹配,关键告警必须能把人"叫醒"。

正确做法:

分级多渠道触达。

# 正确:按级别选渠道
Info     -> 群消息(无需即时处理)
Warning  -> 群消息 + @值班
Critical -> 电话呼叫 + 短信 + 群@所有值班(必须叫醒)

加分点:重要告警要做"送达确认",电话没人接就升级呼下一个人,直到有人确认。


监控大盘设计要点

监控数据采上来后,怎么呈现同样重要。一个设计良好的大盘,能让人在 10 秒内判断"系统现在健不健康"。

| 大盘层级 | 内容 | 受众 |

|---|---|---|

| 全局总览 | 全集群健康状态、核心业务成功率 | 所有人/值班 |

| 单库详情 | 该库 QPS、RT、连接、锁、复制延迟 | DBA |

| 慢查询分析 | 慢 SQL Top N、执行计划变化 | DBA/开发 |

| 容量趋势 | 磁盘/连接数/数据量增长预测 | DBA/SRE |

设计原则:

1. 一眼红绿:总览页用红绿状态灯,正常全绿、异常一眼看到红,不要让人自己找。

2. 关联展示:把业务 RT 和数据库慢查询放在同一屏,便于看因果,而不是分散在不同大盘。

3. 保留对比:每条曲线旁边叠加"上周同期"虚线,环比异常立刻可见。

4. 下钻路径:总览异常点能一键下钻到单库、单条 SQL 的详情,别让人来回切页面。

5. 避免信息过载:一个大盘不超过一屏关键指标,次要信息收进详情页。

监控的终极目标是"出问题前预警、出问题时快速定位",大盘好不好用,直接决定值班同学的反应速度。


监控与告警常见注意事项

监控体系是个系统工程,不是堆指标。以下注意事项帮你避免"采了一堆却用不起来"。

| 注意点 | 建议 | 不做的后果 |

|---|---|---|

| 监控维度 | OS + 数据库内部 + 业务三层都要 | 只看 OS,慢 SQL/锁全失明 |

| 阈值 | 基于历史基线,动态阈值 | 拍脑袋,要么噪音要么漏报 |

| 告警收敛 | 同源告警合并成事件 | 告警风暴淹没关键问题 |

| 告警闭环 | 确认-升级-复盘 | 发了告警没人理 |

| 趋势预测 | 保留历史数据预测容量 | 被动触顶才扩容 |

口诀:三层监控都要采,阈值靠基线不靠猜,告警收敛要人接,趋势提前做预测。


速查表:MySQL 核心监控指标

| 类别 | 指标 | 查看命令 | 告警建议 |

|---|---|---|---|

| 连接 | 连接数/线程 | SHOW GLOBAL STATUS LIKE 'Threads%' | 接近 max_connections 预警 |

| 慢查询 | Slow_queries | SHOW GLOBAL STATUS LIKE 'Slow_queries' | 突增告警 |

| 锁 | 行锁等待 | Innodb_row_lock_current_waits | >0 持续告警 |

| 缓冲池 | 命中率 | Innodb_buffer_pool_read% | 命中率 <99% 关注 |

| 复制 | 延迟 | SHOW REPLICA STATUS | 延迟>10s Warning |

| 磁盘 | 容量/增长 | df -h + 采样 | 80% Warning,85% Critical |

| 错误 | error log | 采集解析 | 关键错误模式突增 |

| 业务 | QPS/RT | performance_schema digest | 核心接口 RT 升高 |


自测练习

1. 为什么只监控 CPU/内存不足以保障数据库?

<details>

<summary>参考答案</summary>

慢 SQL、锁等待、缓冲池命中率、主从延迟等问题发生在数据库内部,OS 指标反映不出来。必须叠加 Slow_queries、行锁等待、缓冲池命中率、复制延迟等数据库内部指标。

</details>

2. 告警阈值应该怎么定才合理?

<details>

<summary>参考答案</summary>

基于历史基线和分位数,用同比环比偏离度告警,而不是拍脑袋固定值。区分 Warning/Critical 级别,避免"狼来了"效应。

</details>

3. 什么是告警风暴?怎么解决?

<details>

<summary>参考答案</summary>

一个根因炸出几十条衍生告警刷屏,淹没关键问题。解法是告警收敛聚合,把同源告警合并成一个事件,并配置告警抑制规则。

</details>

4. 主从延迟为什么是核心业务指标?

<details>

<summary>参考答案</summary>

读写分离下用户写主库后立刻读从库,延迟会导致"读不到刚写的数据",直接影响体验。应监控 Seconds_Behind_Source 并分级告警,必要时用心跳表测真实延迟。

</details>

5. 磁盘监控为什么要分级水位线 + 增长速率?

<details>

<summary>参考答案</summary>

磁盘满是致命故障,95% 才告警就来不及。分级水位(70/80/85%)提前预警,加增长速率能预测何时打满,把被动救火变主动扩容。

</details>

下一篇预告:第 65 章 参数调优踩坑

— 全文完 —回到顶部 ↑
下载推广海报

文章推广海报

《第 64 章 监控与告警踩坑》完整推广海报
DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。