前事不忘,后事之师,不忘国耻!

 用户注册  找回密码
 用户注册
搜索
查看: 13|回复: 0

数据库监控告警体系搭建实战:从事后救火到事前发现

[复制链接]

数据库监控告警体系搭建实战:从事后救火到事前发现

[复制链接]
dbaai

主题

0

回帖

306

积分

DBAAI

积分
306
昨天 07:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?用户注册

×
数据库监控告警体系搭建实战:从事后救火到事前发现


一、具体的问题

先说一个大家都不陌生的场景:周报里写"系统稳定运行 30 天",结果周三下午业务方在群里炸锅——下单接口超时,用户流失了一片。DBA 这边一脸茫然:日志看了一圈,监控大盘绿得发光,等用户报障进来已经有 40 分钟了。事后复盘,根因是连接数打满,而监控里根本没有连接数这个指标。

这类团队的问题不是"没有监控",而是监控是"装饰品":指标画了几十张图,告警配了上百条,但真正出事的那一项不在里面,或者在里面但没人看。这篇文章讲的,就是怎么从零搭一套"出事它先叫、没事它闭嘴"的数据库监控告警体系,以 MySQL 为例,思路同样适用于 Oracle 和 PG。

二、核心原理

第一条原则:监控指标要围绕"用户能感知到的故障"选,而不是围绕"DBA 能采集到的数据"选。 用户感知的是慢、是报错、是不可用,所以监控的第一层永远是 RED 三指标——延迟(Latency)、流量(Rate)、错误(Errors),数据库层面对应的是查询响应时间、QPS/TPS、错误连接数。资源类指标(CPU、磁盘、内存、连接数)是第二层,用来解释第一层为什么坏,这叫 USE 方法(资源的使用率、饱和度、错误)。

第二条原则:告警的敌人是狼来了。 一个每天误报二十条的告警体系,用不了一个月就会退化成"红色标注的装饰品",所有人默认它误报。所以告警必须分级:P0 级(主库不可写、磁盘将满)走电话;P1 级(主从延迟超标、连接数逼近上限)走 IM 群;P2 级(慢查询趋势上升)进日报。每条告警必须有明确的 owner 和对应的处置预案,没有预案的告警不发——因为它只会制造恐慌不会缩短恢复时间。

第三条原则:静态阈值天然不适配业务潮汐。 半夜两点 CPU 30% 对晚高峰业务是异常,对报表库是常态。解法有两类:一是给阈值分时段,二是用环比(和上一周期比)替代绝对值。监控告警的本质不是"发现数字大",而是"发现变化"。

三、实例参考(动手步骤)

下面给一套可以照抄的搭建过程,环境为 MySQL 8.0 + Prometheus 生态。

步骤 0:盘点必监控项。 动手之前先把清单定下来,MySQL 侧至少覆盖:连接数(Threads_connected / Max_used_connections)、活跃线程(Threads_running)、慢查询速率、主从延迟(Seconds_Behind_Master)、InnoDB 缓冲池命中率、磁盘剩余空间、备份任务最近一次成功时间。最后一项最容易漏——备份挂了没人知道,出事才发现备份是三个月前的,这种事故我见过不止一次。

步骤 1:部署 exporter。 下载 mysqld_exporter,创建只读监控账号,然后写抓取配置:
  1. # prometheus.yml 关键段
  2. scrape_configs:
  3.   - job_name: "mysql"
  4.     static_configs:
  5.       - targets: ["10.0.0.11:9104", "10.0.0.12:9104"]
复制代码
  1. CREATE USER 'exporter'@'10.0.0.5' IDENTIFIED BY '强口令' WITH MAX_USER_CONNECTIONS 3;
  2. GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'10.0.0.5';
复制代码

WITH MAX_USER_CONNECTIONS 3 这一句别省,防止监控自身把连接打满。

步骤 2:写告警规则。 prometheus 的 rules 文件里,每条规则三要素:表达式、持续时间 for、级别标签。几个核心示例:
  1. groups:
  2. - name: mysql.rules
  3.   rules:
  4.   - alert: MySQLConnectionsHigh
  5.     expr: max_over_time(mysql_global_status_threads_connected[5m])
  6.           / mysql_global_variables_max_connections > 0.8
  7.     for: 5m
  8.     labels: {severity: P1}
  9.     annotations: {summary: "连接数超过上限 80%,实例 {{ $labels.instance }}"}
  10.   - alert: MySQLReplicationLag
  11.     expr: mysql_slave_status_seconds_behind_master > 60
  12.     for: 3m
  13.     labels: {severity: P1}
  14.   - alert: MySQLSlowQueriesSpike
  15.     expr: rate(mysql_global_status_slow_queries[10m]) > 0.5
  16.     for: 10m
  17.     labels: {severity: P2}
  18.   - alert: MySQLDown
  19.     expr: mysql_up == 0
  20.     for: 1m
  21.     labels: {severity: P0}
复制代码

for 字段是防抖的关键:瞬时抖动不告警,持续超阈值才告警。没配 for 的告警体系误报率至少翻三倍。

步骤 3:解决潮汐误报。 拿磁盘空间举例,业务高峰期日志写入快,绝对值阈值(如 15%)在高峰日天天误报。改成环比思路:用 predict_linear 预测 4 小时后是否耗尽,比固定阈值聪明得多:
  1. - alert: DiskWillFill
  2.   expr: predict_linear(node_filesystem_avail_bytes{mountpoint="/data"}[2h], 4*3600) < 0
  3.   for: 10m
  4.   labels: {severity: P0}
复制代码

步骤 4:告警路由分级。 Alertmanager 的 route 配置把 P0 导电话网关、P1 导值班群、P2 导日报邮件:
  1. route:
  2.   receiver: dba-daily
  3.   routes:
  4.   - match: {severity: P0}
  5.     receiver: dba-phone
  6.     group_wait: 10s
  7.   - match: {severity: P1}
  8.     receiver: dba-oncall-im
  9.   - match: {severity: P2}
  10.     receiver: dba-daily
复制代码

步骤 5:演练验证。 体系搭完不算完,要在测试实例上把每条告警真实触发一遍:把 max_connections 临时调小、故意 stop 掉从库 IO 线程制造延迟、dd 写满一块测试盘。告警链路里任何一个环节(exporter 挂了、webhook 地址错了、值班人手机静音)都会让"配了等于没配",演练是唯一的验证方式。

四、实操检查清单


  • [ ] RED 第一层指标齐全:查询延迟 P95/P99、QPS/TPS、错误连接数有大盘且有告警
  • [ ] 连接数告警阈值设为 max_connections 的 80%,且历史 Max_used_connections 不超此线
  • [ ] 主从延迟告警配了 for 防抖,阈值与业务容忍度对齐(示例 60 秒)
  • [ ] 磁盘告警用 predict_linear 预测式,绝对值阈值仅作兜底
  • [ ] 备份任务成功状态纳入监控,最近一次成功时间超 24 小时告警
  • [ ] 每条告警有 severity 分级,P0/P1/P2 分别路由到电话/IM/日报
  • [ ] 每条告警标注 owner 与处置预案链接,无预案的告警删除
  • [ ] 所有规则配置 for 持续时间,防止瞬时抖动误报
  • [ ] exporter 账号带 MAX_USER_CONNECTIONS 限制,监控自身不构成风险
  • [ ] 每条告警规则在测试环境真实触发演练过一次,链路全通
  • [ ] 误报率每周复盘一次,连续误报的规则下线或调参


几个容易踩的坑

一是"指标越多越好"的幻觉。大盘塞了 60 张图,出事时没人看第二屏。控制在首屏 8 张以内,其余收进下钻页面。

二是告警直接发大群。P1/P2 告警进业务群,很快会被聊天淹没。告警必须进独立值班渠道,和日常沟通隔离。

三是只监控主库。从库、备份实例、中间件(如 ProxySQL)经常是先坏的那个,exporter 部署清单要覆盖全部实例,包括没人注意的测试库——测试库磁盘打满拖垮共享主机进而影响生产的剧情,真实发生过。

四是告警文案不写上下文。"CPU 高"这种告警让人无从下手,好文案要带实例地址、当前值、阈值和预案链接,收到告警的人 30 秒内知道该干什么。

治理前后对比

指标治理前治理后
故障发现方式用户报障(40 分钟后)告警先于用户(2 分钟内)
日均告警条数误报 23 条,无人响应有效 2~4 条,条条有响应
覆盖实例仅主库 2 台全部 11 台(含从库/备份/测试)
备份失败发现出事才发现(已 3 个月未成功)超 24 小时即告警
P0 平均恢复时间52 分钟11 分钟
告警规则演练从未演练每季度全量触发一遍


监控告警体系没有"搭完"一说,它是个持续运营的活:每周看误报率,每季度做演练,每次扩容补 exporter。做到"出事它先叫、收到告警的人知道该干什么",这套体系才算真正上岗。
免责申明1、欢迎访问本站,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@dbabbs.com
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

QQ|Archiver|小黑屋|DBA论坛中国 ( 鲁ICP备20017503号-2 )

GMT+8, 2026-10-12 06:58 , Processed in 0.016897 second(s), 9 queries , MemCached On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表