news 2026/10/15 6:41:04

从零搭建MySQL监控:Prometheus + Exporter + Grafana实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零搭建MySQL监控:Prometheus + Exporter + Grafana实战

1. 监控方案落地前,先聊聊我踩过的坑

先说个真实经历。早几年在一家做SaaS的公司维护线上数据库,MySQL实例跑得好好的,某天下午客户开始零星报障,说页面打开慢、数据保存失败。我们几个人手忙脚乱查应用日志、查网关、查中间件,折腾了将近一个小时,最后登上数据库一看——连接数满了,一堆请求卡在获取连接上。那一刻我是有点崩溃的,因为如果早有一套靠谱的MySQL监控在跑,这个问题打开面板一眼就能看出来,根本不用绕这么大一圈。

后来我把整个监控体系认真搭了一遍,用的就是标题里这套组合:Prometheus + MySQL Exporter + Grafana。整个链路跑通之后,再遇到数据库性能波动、连接数飙升、主从复制卡住这些问题,基本都能在几分钟内定位到原因。这篇文章把我完整的搭建过程和排障经验整理出来,从监控账号的权限设计、各组件的部署方式,到核心指标的含义、可视化面板的导入、PromQL的写法,再到日常维护中比较容易踩的几个坑,一次性说清楚。

这套东西适合什么人参考?如果你手上维护着一两个MySQL实例,想快速建立一套靠谱的监控能力;或者公司已经有Prometheus在跑,就差把数据库接进来;又或者你刚接触监控体系,想找个贯穿“采集-存储-可视化-告警”全链路的练手项目——这篇文章应该都能帮到你。

2. 为什么是这套组合:Prometheus + Exporter + Grafana

2.1 监控方案选型,我是怎么考虑的

做MySQL监控,市面上方案其实不少。比如Zabbix,本身自带MySQL模板,装个agent就能采集;再比如一些云厂商的数据库产品自带监控面板,开箱即用;还有像Lepus这类开源数据库监控系统,也有一批人在用。

那为什么最终选了Prometheus这套?我的理由有几个。一是Prometheus是拉取模型,由Prometheus服务端主动去采集指标,MySQL这边只需要暴露一个端口就行,采集频率、采集目标都可以在服务端统一控制,相比推模型更容易管理和扩容。二是万物皆可Exporter,除了MySQL,主机、Redis、Nginx、Java应用这些都有对应的Exporter,今天接入MySQL,明天接Redis,后天接业务指标,都是一套体系里的事,不用为每种数据库单独学一套监控系统。三是Grafana的可视化能力确实强,面板做出来既直观又专业,领导看的、DBA看的、开发看的,各取所需。

打个不太严谨的比方:Prometheus像个不断巡店的保安,Exporter则是每家店铺门口的设备,监控项统一被采集、存储,Grafana就是保安回传录像的可视化大屏,管理者只管盯屏就行。

2.2 这套体系里的每个角色,分别干哪些活

完整链路里主要有四个组件:

  • Prometheus:监控体系的核心,负责按周期抓取各Exporter暴露的指标,存进时序数据库,并提供PromQL查询能力。
  • mysqld_exporter:专门负责从MySQL里采集状态、变量、InnoDB指标、主从复制状态等数据,翻译成Prometheus能识别的指标格式并暴露出来。
  • Grafana:展示端。连接Prometheus作为数据源,把指标做成图表、仪表盘,也可以配置简易告警。
  • Alertmanager:告警通知组件,可选但建议尽快补上。Prometheus负责产生告警规则,Alertmanager负责把告警送到钉钉、邮件、企业微信。

基础场景可以先把前三个跑起来,告警链路后面再补。文章最后我会单独聊聊告警规则怎么配才能减少误报。

3. 动手搭建:完整部署流程记录

3.1 第一步,先给监控账号分配合适的权限

很多新手喜欢用root账号去做监控采集,图省事。但监控账号一旦泄露,等于把数据库的完全控制权交出去,这个风险没必要冒。正确做法是单独创建一个最小权限账号,mysqld_exporter只要能读状态变量、看主从状态就足够。

在MySQL实例上执行下面这几条SQL:

CREATE USER 'monitor'@'localhost' IDENTIFIED BY 'StrongMonitorPass1!'; GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'monitor'@'localhost'; FLUSH PRIVILEGES;

三个权限分别解释一下:SELECT让Exporter能查询性能相关的表;PROCESS用来读取线程、连接相关的状态;REPLICATION CLIENT用来查看主从复制状态。比如复制状态、复制延迟这些关键信息,缺了这个权限就读不到。

如果数据库和Exporter不在同一台机器,把@'localhost'换成对应的访问来源地址,或者按需配置。另外MySQL 8.0默认的认证插件是caching_sha2_password,老版本的mysqld_exporter可能连不上,建议在创建用户时显式指定:

CREATE USER 'monitor'@'localhost' IDENTIFIED WITH mysql_native_password BY 'StrongMonitorPass1!';

这一步比较实际但经常被人忽略,建议直接从开始就规避。

提示:监控账号的密码配置文件不要给太宽的权限,建议文件属主设为运行Exporter的用户,权限设为600。

3.2 部署mysqld_exporter:采集器怎么配置才完整

mysqld_exporter是纯Go编译的二进制,跑起来很简单,但有几个参数和配置细节值得注意。

先去GitHub Releases下载对应平台的压缩包,解压后就是一个可执行文件。官方推荐通过配置文件传数据库凭据,不要直接写在命令行参数里。新建一个配置文件,比如/etc/mysqld_exporter/.my.cnf:

[client] user=monitor password=StrongMonitorPass1!

启动方式建议注册成systemd服务,这样开机自启、崩溃自动拉起都不用手动管。服务文件写这样:

[Unit] Description=MySQL Exporter After=network.target [Service] User=mysqld-exp Group=mysqld-exp Type=simple ExecStart=/usr/local/mysqld_exporter/mysqld_exporter \ --config.my-cnf=/etc/mysqld_exporter/.my.cnf \ --web.listen-address=:9104 Restart=always [Install] WantedBy=multi-user.target

启动后先看两个地方。一是curl http://localhost:9104/metrics能不能返回指标;二是重点确认指标里有下面这些:

  • mysql_up:值为1表示Exporter成功连上了MySQL,0就是连接失败,这个是排障的第一排查点。
  • mysql_global_status_threads_connected:当前连接数。
  • mysql_global_status_innodb_buffer_pool_read_requests和mysql_global_status_innodb_buffer_pool_reads:计算InnoDB缓存命中率的基础数据。
  • mysql_slave_status_seconds_behind_master:主从复制延迟,监控从库时这个指标至关重要。

注意:不同版本的mysqld_exporter在指标命名上会有差异,比如0.15版本里mysql_global_status_commands_total这类指标带_total后缀,而threads_connected这类状态量则不带。网上的很多PromQL都是基于特定版本写的,照抄之前一定要先在/metrics页面里确认实际的指标名。

3.3 部署Prometheus:配置抓取任务并接入服务

Prometheus同样是一个二进制文件,官方提供了Linux、Windows、macOS各平台包。我用的是二进制部署方式,下载解压后用systemd管理,也比较符合后续维护习惯。

重点在于prometheus.yml,这是Prometheus的核心配置。一个最小可用的配置长这样:

global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'mysql' static_configs: - targets: ['localhost:9104'] labels: instance: 'db-prod-01'

scrape_interval控制采集频率。15秒是推荐值,能在数据粒度和数据库压力之间取得平衡。有人喜欢调到5秒甚至1秒,觉得数据更实时,但实际意义不大,反而会给数据库和监控本身增加无谓的查询开销,采集太频繁对Exporter和Prometheus存储也是一种负担。

启动命令也可以注册成systemd服务:

[Unit] Description=Prometheus Server After=network.target [Service] User=prometheus Group=prometheus Type=simple ExecStart=/usr/local/prometheus/prometheus \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/var/lib/prometheus Restart=always [Install] WantedBy=multi-user.target

启动后访问http://localhost:9090/targets,能看到两个抓取目标。如果mysql这一行的状态是UP,说明Prometheus已经能正常抓到MySQL指标了;状态是DOWN就继续看到第四节排障部分。

3.4 部署Grafana:数据源接入与面板导入

Grafana安装方式比较多,可以用官方仓库加apt/yum源,也可以用Docker跑,甚至直接下载二进制包。装好之后浏览器打开http://localhost:3000,默认账号密码都是admin,第一次登录会要求改密码,按提示设置即可。

然后添加Prometheus数据源,路径是 Configuration → Data Sources → Add data source → 选择Prometheus。URL填http://localhost:9090,其他保持默认,点击Save & Test看到“Successfully queried the Prometheus API”提示就说明数据源通了。

监控面板可以直接导入社区现成的模板,省去从零画图的时间。在Grafana里点 Dashboards → Import,输入模板ID 7362,这是社区里比较经典的MySQL Overview面板,包含了连接数、查询量、缓冲池命中率、主从状态等常用图表。导入时选择刚才创建的数据源,确定即可。

模板导入之后,默认的图表几乎不需要改动就能用。但有一点要提醒:模板指标名如果和当前Exporter版本对不上,某些图会显示No Data,这是正常现象,根据实际指标名改一下对应面板的PromQL就行。

3.5 如果你不想装一堆二进制:Docker Compose一键方案

如果你想快速体验整套流程,或者只是本地测试,Docker Compose可能是最省事的方式。写一个docker-compose.yml:

version: '3' services: prometheus: image: prom/prometheus:v2.47.0 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - "9090:9090" mysqld-exporter: image: prom/mysqld-exporter:v0.15.1 environment: - DATA_SOURCE_NAME=monitor:StrongMonitorPass1!@(127.0.0.1:3306)/ ports: - "9104:9104" grafana: image: grafana/grafana:10.1.0 ports: - "3000:3000"

这种方式的优点是快,docker compose up -d一条命令全部起来。缺点是容器网络在隔离环境里比较容易让人发懵,比如Exporter容器访问宿主机MySQL时要特别注意网络配置。如果数据库不在宿主机上而是独立服务器,那这套方案倒是不错的选择。

4. 核心监控指标解读与自定义面板实战

4.1 MySQL监控到底要盯哪些指标

很多初学者导入一个Dashboard就完事了,图很多,但不知道每张图在讲什么,出问题也不知道去哪里看。我个人总结下来,无论面板多花哨,核心就是盯下面这几类。

可用性:mysql_up是第一步,它反映的是Exporter到MySQL连通性的状态,值不是1就是0。0的时候其他指标统统不用看了,先查连接。

连接与负载:连接数是最容易暴雷的指标。单个MySQL实例的连接数上限由max_connections决定,默认通常就100多到几百,一旦触发too many connections错误,应用层就会连环报错。用连接数使用率来表达更直观:

mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100

这个值超过80%就要警惕,逼近100%就说明连接快被打满了。再配合看aborted_connects这个指标,就能区分出到底是并发真的高,还是大量连接被异常中断导致。

查询量与性能:QPS和慢查询是两个特别常用的指标。

# QPS 实时查询速率 sum(rate(mysql_global_status_queries[5m])) # 慢查询速率 rate(mysql_global_status_slow_queries[5m])

QPS出现尖峰或断崖式下降,往往对应着业务流量变化或SQL阻塞。慢查询则没有固定阈值,要结合业务特点观察基线和趋势,慢查询突然翻倍,大概率是某些SQL写入走了坏索引或者锁等待变多了。

InnoDB缓冲池命中率:InnoDB Buffer Pool是MySQL的内存缓存核心,命中率越高,磁盘IO越少。参考公式:

(1 - mysql_global_status_innodb_buffer_pool_reads / mysql_global_status_innodb_buffer_pool_read_requests) * 100

日常保持在99%以上算是健康,如果跌破95%,说明缓存里装不下的数据太多了,可能Buffer Pool设置偏小,或者存在大量全表扫描把缓存冲掉了。

主从复制:复制延迟和复制线程状态是监控从库时的生命线。真实生产里主从同步卡住后,从库数据会越来越旧,如果流量切到从库,直接就是数据不一致的事故。

# 复制延迟秒数 mysql_slave_status_seconds_behind_master # 复制线程是否正常,1 表示正常 mysql_slave_status_slave_io_running mysql_slave_status_slave_sql_running

建议把这三个指标做成一个单独的“主从复制状态”面板,再有条件的话配一条延迟告警,这是从库出问题时最先响的报警器。

4.2 从零定制一块自定义面板:以连接数为例

不用完全依赖社区模板,日常我也会自己建一些针对性面板。在Grafana里新建Panel,选择Prometheus数据源,查询框里就写对应的PromQL表达式。

比如连接数情况,可以添加三个Query:

图表内容PromQL表达式类型
当前连接数mysql_global_status_threads_connected实时曲线
最大连接数mysql_global_variables_max_connections常量参考线
连接数使用率mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100百分比曲线

把连接数的图阈值设为80和95,mysql_global_variables_max_connections设在99百分位,面板的可见性和可读性就都出来了。

新建面板保存到Dashboard里,填写好名称,选好数据源和表达式即可。整个过程大概十分钟,比等着模板更新来覆盖需求要靠谱得多。

4.3 告警规则配置:怎么告才能不变成狼来了

先给Prometheus配置告警规则文件。在prometheus.yml里加一行:

rule_files: - '/etc/prometheus/rules/mysql.yml'

然后在/etc/prometheus/rules/mysql.yml里写基础规则:

groups: - name: mysql_alerts rules: - alert: MySQLDown expr: mysql_up == 0 for: 1m labels: severity: critical annotations: summary: "MySQL 实例 {{ $labels.instance }} 不可达" description: "Exporter 连不上 MySQL,请检查数据库状态和网络。" - alert: MySQLHighConnections expr: mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100 > 85 for: 5m labels: severity: warning annotations: summary: "MySQL 连接数过高({{ $value | humanizePercentage }})" description: "实例 {{ $labels.instance }} 连接使用率超过 85%,持续 5 分钟,请排查连接池配置和慢 SQL。" - alert: MySQLReplicationDelay expr: mysql_slave_status_seconds_behind_master > 30 for: 1m labels: severity: warning annotations: summary: "MySQL 主从复制延迟过大" description: "从库 {{ $labels.instance }} 复制延迟 {{ $value }} 秒,请检查复制线程和主库负载。"

这里有几个细节要特别说到:

for: 5m这个参数很关键。比如连接数使用率瞬间超过85%不能立即触发报警,因为可能是短时间的峰值抖动,阈值内有个5分钟的稳定周期再报,可以有效避免“狼来了”式的骚扰报警。

告警从Prometheus发出来,如果想把告警真正推送到钉钉或企业微信群,需要部署Alertmanager并在prometheus.yml中配置alertmanager的地址。我通常会把Alertmanager单独部署一套,再在配置里给不同告警配不同的路由。这部分内容展开讲又是很长一篇,先不赘述,基础规则先跑起来,告警能触发了,后面再逐步优化接收渠道和收敛策略。

5. 实战中的常见坑和问题定位方法

5.1 问题速查表:先对照这些现象排查

搭建和日常运行中最常遇到的问题,我整理成了一张速查表:

问题现象可能原因排查处理
Prometheus Targets页显示DOWNExporter进程没起来或端口不通curl http://localhost:9104/metrics看是否返回;检查--web.listen-address端口配置
mysql_up值为0Exporter连不上MySQL检查数据库账号密码、网络连通性、授权IP是否匹配
面板一片No DataPrometheus没抓到数据;模板指标名和实际不匹配先看Targets是否UP;再到Exporter的metrics页面核对真实的指标名
连接数类指标一直为0账号缺PROCESS权限或Exporter版本差异补权限GRANT PROCESS ON *.*;查询SHOW STATUS确认取值方式
主从复制指标取不到缺REPLICATION CLIENT权限,或从库没开复制补权限;执行SHOW SLAVE STATUS确认线程状态正常
Grafana保存时报数据库错误Grafana使用的SQLite或Postgres实例异常检查Grafana数据目录权限;或确认外部数据库连接正常

5.2 三个高频率踩坑场景的详细排障过程

场景一:Targets显示DOWN,一切刚搭建好

Prometheus Targets页面看到mysql的target是红色DOWN,第一反应不是改Prometheus配置,而是自己先模拟一下Prometheus的行为:在Prometheus服务器上执行curl http://MySQL所在IP:9104/metrics。如果命令超时或拒绝连接,说明网络层不通或Exporter没有监听。常见是防火墙没放行9104端口,或者Exporter默认只监听了127.0.0.1,外部服务器访问不到。

修改检查参数:

curl -v http://127.0.0.1:9104/metrics # 本机检查 curl -v http://<exporter-ip>:9104/metrics # 从Prometheus机器上检查

如果本机通、外机不通,优先看防火墙和监听地址。把Exporter启动参数改为--web.listen-address=0.0.0.0:9104表示全地址监听(前面systemd配置里没写这个参数时只监听默认地址,暴露外部时应该加上)。

场景二:数据库没宕机,mysql_up却是0

mysql_up为0和Targets DOWN不是一回事。Targets DOWN说明抓取动作本身失败;如果Targets是UP但mysql_up为0,说明Exporter活着,但它连不上MySQL。

先从Exporter的启动日志看,通常是Error级别会直接打出Error establishing database connection。如果是连接被拒绝,重点检查两件事:一是数据库监听是否只绑了localhost,账号授权的主机范围能不能覆盖Exporter的来源IP;二是Exporter配置的密码是不是有转义问题,密码包含特殊字符时.my.cnf里要写成password="xxxx"带引号的格式。

场景三:导入7362模板后很多图No Data

模板7362是很经典但也是“老了”的模板。旧模板引用的指标名比如mysql_global_status_queries、mysql_global_status_commands_total,在0.15版本里可能叫mysql_global_status_commands_total{command="select"}。Exporter每次启动后,/metrics页面的指标名就是最权威的字典。

另外一个很容易忽略的原因:新版Exporter有些Collector是默认关闭或者需要显式开启的,比如主从复制相关的collect.slave_status、InnoDB相关的collect.innodb_metrics。启动命令里显式加:

--collect.slave_status --collect.innodb_metrics

尽量用命令行显式开启,而不是自己逐个改模板,这样减少边边角角的遗漏。

5.3 给Exporter加补充采集:连接信息也能落到监控里

有一点经常被忽略:监控不只监控“库本身”,数据库所在服务器的资源耗损也直接影响MySQL表现。比如磁盘满了、CPU打满、Swap消耗严重,这些在没有主机监控时就是盲区。

推荐在Prometheus配置里再加一个node_exporter的抓取任务,地址指向MySQL所在服务器的9100端口:

- job_name: 'mysql-node' static_configs: - targets: ['10.0.0.100:9100'] labels: instance: 'db-prod-01'

然后就可以把node_filesystem_avail_bytes、node_cpu_seconds_total这些指标拿来做关联分析。MySQL报慢查询的时候,看一眼磁盘或CPU是不是已经被打满,往往能直接回答“为什么会慢”。

6. 我在运维实践中总结的几条心里话

整个体系我前前后后在不同环境里搭过很多次,从最早的单实例监控,到后来多套主从、一主多从、跨机房场景,过程中最重要的收获就是:监控的价值不是“能看到”,而是“能提前发现”和“能快速定位”。

如果你现在刚开始接触这套体系,我觉得有一点值得优先投入:监控面板不求多,但求每个面板都有明确的用途。我从一开始一股脑几十个图表,到后来删繁就简,只保留业务层最能反映问题的十来个指标,实际用下来反而更高效。

另一点是告警策略调整没有终点。连接数报警的阈值,不同业务天差地别,我们有一次把阈值从80%调到90%才逐渐稳定,因为这个实例本身就有大量长连接,峰期连接数常年维持在85%上下,如果阈值太敏感,基本每天都要被轰炸一次。后来将“for: 5m”改为“for: 10m”,误报少了很多。

建议你刚上线时先观察一到两周的指标基线,再把阈值定在上面1.5倍左右的位置。监控不是一次性工程,它需要随着业务的增长一起迭代。把基础设施搭好,把指标看明白,后面接任何业务监控都只是加配置的事情。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 6:40:27

Java入门第4天:方法、数组与引用传递的踩坑复盘

今天是学习Java第4天。说实话&#xff0c;前三天我一直在“跟着感觉走”&#xff1a;第一天装环境、配置JDK、敲了几个Hello World的变体&#xff1b;第二天啃变量、数据类型和运算符&#xff0c;练到逻辑运算符时一度怀疑自己小学数学没学好&#xff1b;第三天学会了if、switc…

作者头像 李华
网站建设 2026/10/15 6:39:57

context-mode:AI辅助开发中的上下文隔离与回收实战

做 AI 辅助开发半年多&#xff0c;我最头疼的问题不是模型不够聪明&#xff0c;而是它总"串味"——早上还在写 A 项目的接口文档&#xff0c;下午打开对话工具问 B 项目的需求&#xff0c;AI 张口就是 A 项目的表结构和代码风格。长期多项目并行的人应该都有同感&…

作者头像 李华
网站建设 2026/10/15 6:38:56

基于RA-AF特征与GMM聚类的声发射裂纹模式识别Matlab实现

简介&#xff1a;针对材料力学与无损检测中的裂纹模式识别问题&#xff0c;这份PDF文档提供了一套基于RA-AF特征与高斯混合模型&#xff08;GMM&#xff09;的Matlab实现代码。核心思路是不预先划分裂纹分界线&#xff0c;而是借助期望最大化&#xff08;EM&#xff09;迭代算法…

作者头像 李华
网站建设 2026/10/15 6:38:33

从零搭建内部数据聚合系统:REA项目的架构决策与踩坑复盘

如果你翻过某团队内部的项目清单&#xff0c;大概率见过一类只有代号、没有详细介绍的项目——我这次负责的 REA 就是其中之一。刚拿到手的时候&#xff0c;除了这个名字&#xff0c;只剩一条需求&#xff1a;“把各处散落的运行数据收拢起来。”听起来很简单&#xff0c;但真正…

作者头像 李华
网站建设 2026/10/15 6:38:10

DINA认知诊断模型:从总分到知识点画像的题诊断研究

简介&#xff1a;这是一篇发表于《中国考试》2013年第1期的认知诊断DINA模型研究综述&#xff0c;作者为南京师范大学张潇、沙如雪&#xff0c;适合心理测量学、教育统计与个性化教学研究者阅读。资源以PDF格式提供&#xff0c;包含期刊原文共1个文件&#xff0c;压缩包约1.31M…

作者头像 李华
网站建设 2026/10/15 6:38:07

堆排序原理解析:完全二叉树、堆化与下沉调整的底层逻辑

1. 为什么堆排序值得你花20分钟真正搞懂——它不是“另一个排序”&#xff0c;而是数据结构思维的分水岭很多人学堆排序&#xff0c;止步于“建堆→交换→调整”这九个字。背过代码&#xff0c;跑过Demo&#xff0c;考试能写&#xff0c;但一问“为什么非得用完全二叉树结构”“…

作者头像 李华