MySQL 性能监控实战:从零搭建 Prometheus + Grafana 监控告警体系(附排查 SOP)
📌 今日关键词:性能监控、PMM、Prometheus、Grafana、慢查询、告警、指标体系
大家好,我是数据库小学妹👋
前面我们学习了锁机制、MVCC、慢查询诊断这些"事后分析"的技术。但你知道
“数据库目前处于什么状态?QPS 多少?Buffer Pool 命中率是什么水平吗?”
听到QPS、命中率这些词是不是很懵?所以SQL写得好是一回事,知道数据库在"跑"什么状态是另一回事。
今天把我从零学监控的经历整理出来,新手也能从零搭建。
一、为什么需要监控?
先讲一个案例:
某平台电商大促,系统突然变慢。开发找运维,运维找 DBA,DBA 说"等我连上去看看"。这一套流程走了 15 分钟,用户已经跑到竞品下单了。
如果有一套监控,慢查询超过阈值就自动告警,早在用户察觉之前就能介入。
监控能帮你做什么?
| 目的 | 具体场景 |
|---|---|
| 实时感知 | QPS 突然掉底、连接数打满,立刻知道 |
| 故障预警 | Buffer Pool 命中率下降,提前扩容 |
| 排障加速 | 出问题时不用"我觉得慢了",直接看指标 |
| 容量规划 | 过去三个月 QPS 趋势,决定什么时候扩容 |
数据这东西不会说谎。嘴上说"不慢"没用,监控图表才说了算。
二、监控的五维指标体系
搞监控第一件事不是选工具,而是搞清楚该看什么。我把 MySQL 的核心指标分成五个维度:
🧠 维度 1:资源使用
| 指标 | 含义 | 告警阈值参考 |
|---|---|---|
| CPU 使用率 | MySQL 进程 CPU 占用 | > 80% 持续 5 分钟 |
| 内存使用 | InnoDB Buffer Pool 占用 | 实际使用 > 可用内存 90% |
| 磁盘 IO | 每秒读写次数 IOPS | 写 IO 延迟 > 20ms |
| 磁盘空间 | 数据目录可用空间 | < 20% |
| 网络吞吐 | 每秒收发流量 | 接近带宽上限 |
这些指标别在 MySQL 里查,用系统命令更快:
# CPUtop-p$(pgrep mysqld)-n1# 内存free-h# 磁盘 IOiostat-x13# 磁盘空间df-h/var/lib/mysql🧠 维度 2:连接与线程
-- 当前连接数 vs 最大连接数SHOWVARIABLESLIKE'max_connections';SHOWSTATUSLIKE'Threads_connected';-- 查看连接来源和状态SELECTuser,host,db,command,time,stateFROMinformation_schema.processlistWHEREcommand!='Sleep'ORDERBYtimeDESC;连接池满了最常见的问题——用户报"无法连接数据库",大概率是连接数被打满。
🧠 维度 3:查询性能
-- QPS 近似计算(两次查询间隔内的差值)SHOWSTATUSLIKE'Questions';SHOWSTATUSLIKE'Uptime';-- 慢查询数量SHOWSTATUSLIKE'Slow_queries';-- 全表扫描次数SHOWSTATUSLIKE'Select_scan';关注三个关键指标:
- QPS 突降→ 可能有锁等待
- Slow_queries 飙升→ SQL 性能退化或缺少索引
- Select_scan 增长→ 全表扫描增多
🧠 维度 4:InnoDB 引擎
-- Buffer Pool 命中率(核心指标!)SHOWSTATUSLIKE'Innodb_buffer_pool_read%';-- 公式:1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests) × 100%-- 目标:> 99%-- 行锁等待SHOWSTATUSLIKE'Innodb_row_lock_waits';SHOWSTATUSLIKE'Innodb_row_lock_time';-- 脏页比例SHOWSTATUSLIKE'Innodb_buffer_pool_pages%';Buffer Pool 命中率是我最关注的指标之一。低于 98% 说明内存不够用了,该扩了。
🧠 维度 5:主从同步
SHOWSLAVESTATUS\G-- 关注两个字段:-- Seconds_Behind_Master(延迟)-- Slave_IO_Running / Slave_SQL_Running(必须都是 Yes)三、三层工具选型
🟢 新手级:PMM(Percona Monitoring and Management)
PMM 是 Percona 开源的监控平台,基于 Prometheus + Grafana,开箱即用。
安装(docker 一把梭):
# 拉取 PMM Serverdockerrun-d-p80:80-p443:443\--namepmm-server\percona/pmm-server:2# 在 MySQL 机器上安装 PMM Clientyuminstallpmm2-client# 或apt-getinstallpmm2-client# 注册客户端到服务端pmm-admin config --server-insecure-tls --server-url=https://admin:admin@<pmm-server-ip>然后刷浏览器打开 PMM 面板,你会看到一个详细的仪表盘——QPS、连接数、Buffer Pool 命中率、慢查询趋势,全在里面。
🌐 进阶级:搭建你自己的 Grafana 面板
PMM 好用,但如果你已经有 Prometheus 体系,自己搭一套更灵活。
架构:
MySQL → mysqld_exporter → Prometheus → Grafana步骤 1:安装 mysqld_exporter
# 创建监控用户CREATEUSER'exporter'@'%'IDENTIFIED BY'password';GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO'exporter'@'%';# 安装运行wgethttps://github.com/prometheus/mysqld_exporter/releases/latest ./mysqld_exporter--mysqld.username=exporter--mysqld.password=password步骤 2:Prometheus 配置
# prometheus.yml-job_name:'mysql'static_configs:-targets:['your-mysql-host:9104']步骤 3:Grafana 仪表盘
Grafana 有现成的 MySQL 仪表盘模板:
- Dashboard ID: 7362(MySQL Overview)
- Dashboard ID: 9623(MySQL InnoDB Metrics)
导入就能用,不用从零画图。
🔧 兜底级:纯 SQL 脚本
不是所有环境都能装监控工具。开发环境、内网测试库有时候只能自己跑 SQL 看:
-- 一键快照脚本(适合做定时任务)SELECTNOW()ASsnapshot_time;SELECT'--- QPS ---'ASindicator;SELECTROUND(QUESTIONS/UPTIME,2)CURRENT_QPS,ROUND(QUESTIONS/UPTIME,2)AVG_QPSFROM(SELECTVARIABLE_VALUEASQUESTIONSFROMperformance_schema.global_statusWHEREVARIABLE_NAME='Questions')q,(SELECTVARIABLE_VALUEASUPTIMEFROMperformance_schema.global_statusWHEREVARIABLE_NAME='Uptime')u;SELECT'--- Buffer Pool 命中率 ---'ASindicator;SELECTCONCAT(ROUND((1-reads/requests)*100,2),'%')ASbuffer_hit_rateFROM(SELECT(SELECTVARIABLE_VALUEFROMperformance_schema.global_statusWHEREVARIABLE_NAME='Innodb_buffer_pool_reads')ASreads,(SELECTVARIABLE_VALUEFROMperformance_schema.global_statusWHEREVARIABLE_NAME='Innodb_buffer_pool_read_requests')ASrequests)t;SELECT'--- 连接数 ---'ASindicator;SELECT(SELECTVARIABLE_VALUEFROMperformance_schema.global_statusWHEREVARIABLE_NAME='Threads_connected')AScurrent,(SELECTVARIABLE_VALUEFROMperformance_schema.global_variablesWHEREVARIABLE_NAME='max_connections')ASmax;放到 crontab 里每 5 分钟跑一次,输出到文件,自己整理看趋势。
四、告警规则怎么设?
有监控没告警,等于闭着眼睛开车。生产环境最必要的几条告警:
| 告警项 | 条件 | 级别 |
|---|---|---|
| 连接数过多 | 当前连接 > 最大连接 × 0.8 | P1(紧急) |
| 慢查询骤增 | 5 分钟内慢查询 > 50 | P2(重要) |
| Buffer Pool 命中率下降 | < 95% 持续 10 分钟 | P2(重要) |
| 磁盘空间不足 | < 10% 可用 | P1(紧急) |
| 主从延迟 | > 10 秒持续 5 分钟 | P2(重要) |
| QPS 突降 | 下降 > 50% 持续 3 分钟 | P1(紧急) |
告警通知渠道
- P1→ 短信 + 电话 + IM 群通知
- P2→ IM 群通知 + 邮件
别把所有告警都设成 P1,不然会被"狼来了"效应淹没。
五、监控实战 checklist
这是我学监控的计划,按这个顺序来对新手友好:
Phase 1:先看(第 1 周)
# 每天跑一遍,感受数据库的"脉搏"SHOW STATUS;SHOW ENGINE INNODB STATUS\G SHOW PROCESSLIST;不用监控工具,每天手动跑几次这些命令,感受一下 QPS、连接数、慢查询的变化。先建立"手感"。
Phase 2:再看(第 2-3 周)
- 安装 PMM,导入默认仪表盘
- 学会看 QPS 趋势图、慢查询列表
- 每天看一眼 Buffer Pool 命中率
Phase 3:会报警(第 4 周)
- 配置连接数告警(P1)
- 配置慢查询告警(P2)
- 确认告警通道畅通
Phase 4:能排障(持续)
- 梳理常见性能问题的监控排查路径
- 把排查经验写成 SOP
六、我的排查 SOP:三步定位法
当告警响起,按这三步来:
第一步:全局扫一眼
QPS ↓ 50% → 继续 ↓ 连接数 ↑ 300% → 连接池打满 → 可能是慢查询导致连接堆积 慢查询 ↑ 10x → 确认!有慢查询 → 进入第二步第二步:定位慢查询元凶
-- 查当前正在跑的慢 SQLSELECTtrx_mysql_thread_idASthread_id,trx_queryAScurrent_sql,TIMESTAMPDIFF(SECOND,trx_started,NOW())ASrunning_secondsFROMinformation_schema.innodb_trxWHEREtrx_state='RUNNING'ORDERBYrunning_secondsDESC;-- 或者从慢查询日志查历史-- 先确认慢查询日志是否开启SHOWVARIABLESLIKE'slow_query_log';-- 分析最近 50 条慢查询mysqldumpslow-t50/var/lib/mysql/slow.log第三步:分析慢查询
用 EXPLAIN 看执行计划(这个我们之前的文章详细讲过),定位是全表扫描还是索引没走对。
这套流程在大促值班时用过一次:凌晨 2 点 QPS 掉底告警,顺着三步走,3 分钟定位到一个缓存过期导致的 full join,扩容后恢复正常。
七、今日学习心得
- 监控不是装完工具就完事,指标体系设计比工具重要
- 五个维度(资源/连接/查询/引擎/主从)覆盖 90% 的性能问题
- PMM 适合新手快速上手,Prometheus + Grafana 适合有基础的自己定制
- 告警要分级,别把 P2 的事设成 P1
- 先建立手感,再上工具——顺序很重要
👋 我是数据库小学妹一个用设计师思维学数据库的转行人。我们一起,用监控让数据库问题早发现、早解决!💕
本文示例基于 MySQL 8.0 + InnoDB。不同环境配置可能有差异,请结合实际调整。
