资讯动态

从零搭建Prometheus监控MySQL:部署、告警与Grafana可视化实战

发布时间:2026/10/15 6:41:12 来源:尧图企业网站定制
1. 为什么要用Prometheus监控MySQL从一次事故说起刚接手这套系统的时候MySQL实例已经有几十台在跑分布在不同的业务线里。某天业务方半夜打电话过来说批量任务全挂了排查到最后才发现是某台从库的磁盘早就满了主库的binlog同步中断了好几个小时没被发现。那时候监控全靠人肉巡检脚本定时去查数据库状态慢、延迟高而且没有人会半夜盯着告警看。那次事故之后我才决定把整个数据库监控体系从零搭起来。当时摆在面前的选项其实不少Zabbix、Nagios、InfluxDB那套都有各自的拥趸。最终选定了Prometheus mysqld_exporter Grafana的组合核心原因是这套方案在云原生时代太顺了。Prometheus 天然支持多维数据模型指标抓取用Pull模式MySQL的状态变量、InnoDB 指标、复制状态这些都能量化成一个又一个的 gauge 和 counter配合Grafana做可视化数据从采集到展示的链路非常短。对于已经跑着 Kubernetes 和微服务的团队来说监控MySQL只是Prometheus生态的一部分后续要扩展监控应用、资源、中间件完全是同一套基础设施不会出现监控孤岛。这篇内容适合谁看如果你是刚从脚本巡检升级到专业监控体系的运维工程师或者被分到了数据库稳定性相关的活又或者你只是想把 MySQL 的指标好好用起来这套方案都可以直接照着抄。我会把部署过程、配置细节、告警规则、可视化面板以及踩过的坑和排查思路全部记录下来尽量做到拿来就能用、照着就能跑。2. 监控架构设计先理清楚数据怎么流动2.1 核心组件和数据流整套监控链路涉及四个核心角色先画清楚它们各自负责什么后面配置的时候才不会被绕晕。Prometheus 服务端负责定时拉取指标、存储时序数据、执行告警规则。它会按配置的 interval 主动访问 exporter 暴露的 HTTP 接口拿到监控数据后打上时间戳存入本地时序库。mysqld_exporterPrometheus 和 MySQL 之间的翻译官。它用我们创建的监控账号连接目标 MySQL通过执行 SHOW GLOBAL STATUS、SHOW GLOBAL VARIABLES、SHOW MASTER STATUS、SHOW SLAVE STATUS 等 SQL 取到数据库内部的状态快照再转换成 Prometheus 的时间序列格式在 9104 端口上暴露出来。默认的采集器并不算多很多重要指标依赖额外开启的 collector。Grafana负责把时序数据变成看得懂的图表和仪表盘。它不直接对接 MySQL而是通过 Prometheus 的数据源查询 PromQL 表达式渲染成曲线图、热力图、表格等各种形式同时也可以在上面配置告警通知。AlertmanagerPrometheus 生态里的告警中枢。Prometheus 本身只负责判断告警规则是否触发真正负责去重、分组、静默以及通过 webhook、邮件、企业微信、钉钉等方式通知人的是 Alertmanager。数据流向是单向且清晰的mysqld_exporter 从 MySQL 取指标Prometheus 从 mysqld_exporter 拉指标Grafana 和 Alertmanager 从 Prometheus 读取指标和触发状态。这个单向链路让问题排查变得简单哪个环节没数据顺着链路查就行不需要到处臆测。2.2 为什么必须用独立的监控账号直接拿 root 账号给 exporter 用是最常见的坑这个我一开始也干过。虽然配置简单但风险非常大监控脚本挂了不会出问题但如果 exporter 存在漏洞被攻击数据库权限就被直接拿走了。更麻烦的是root 账号在 binlog 里留下的操作记录会干扰审计排查。正确的做法是创建最小权限的专用账号这也是整套方案里我认为优先级最高的安全设计。给监控账号分配的权限只需要 PROCESS、REPLICATION CLIENT 和 SELECT分别用于查看线程状态和服务器变量、查看复制信息、读取状态变量。这里有一行配置值得提醒给远程访问设置网段限制避免监控账号被公网任意主机探测。在 MySQL 8.0 中创建监控账号的语句和管理员账号的权限体系有一些变化需要留意默认认证方式对客户端兼容性的影响。exporter 通过 TCP 方式连接时需要配套的加密与认证选项配置老旧版本可能不兼容新的默认认证插件连接不上时优先从认证方式排查。在后续配置 exporter 时不要图省事把连接密码直接明文写在命令行参数里。文件方式加载凭证配合合理的文件权限能避免进程列表暴露密码的风险命令行的信息容易被同主机的其他用户看到。3. 部署实操从零搭建一套能用的监控环境3.1 环境准备与Prometheus部署先说我这边的环境供你参考操作系统用的是 Linux 发行版MySQL 跑了 5.7 和 8.0 两个版本Prometheus 和 Grafana 都部署在独立的服务器上。实际部署时版本选择建议遵循一个原则Prometheus、exporter、Grafana 尽量选择官方最新稳定版而不是随便 apt install 或 yum install 拿到的版本仓库里的包往往落后好几个大版本。二进制部署是兼容性最好的方式也最容易理解组件之间的关系。Prometheus 本身就是单个二进制文件加一个目录不依赖额外的运行环境。官方下载页面拿到 tarball 后解压出来就是可用的服务端程序。特别说明一下存储目录prometheus.yml 是主配置文件data 目录存放时序数据控制台和库接口都通过 HTTP 暴露。启动时指定配置文件路径后续把 service 文件写好交给 systemd 管理就行。注意data 目录务必放在磁盘空间充足且独立的分区如果和系统目录共用一块且空间很小时序数据写满后不止监控不可用整个服务器都可能被拖垮。我见过不止一次因为监控服务器磁盘被时序数据撑爆导致主机卡死的案例。再有就是启动参数中的监听地址问题。如果这台 Prometheus 后续还要被其他区域的监控数据汇入或者办公网要直接访问查询页面就要把默认的 localhost 换成可访问的地址或者通过反向代理控制访问。生产环境建议不要图方便把监听地址直接裸奔到公网Prometheus 自带的 web 控制台没有认证能力。3.2 监控账号的创建把权限给得刚刚好监控账号的创建要在每台被监控的 MySQL 实例上都执行一遍。为了批量操作方便我写了个脚本用循环去执行但脚本本身不复杂核心就是下面这段 SQL我拆开来解释每一行的意图。CREATE USER mysqld_exporter192.168.1.% IDENTIFIED BY StrongPassword123; GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO mysqld_exporter192.168.1.%; FLUSH PRIVILEGES;第一行创建用户并限制来源网段IDENTIFIED BY 后面是密码。这里主机部分是重点写 192.168.1.% 意味着只有这个网段的机器能连exporter 部署在什么网段这里就写什么网段。第二行是授权库表范围写.是因为状态变量和复制信息不属于某个具体库必须全局权限才能读取。第三行刷新权限让修改立即生效。如果你用的是 MySQL 8.0注意默认的认证插件是 caching_sha2_password。某些版本较低的客户端或者驱动连接时可能报认证插件不支持那时候要么升级连接库要么在创建用户时显式指定 mysql_native_password不过后者会降低安全级别升级客户端才是更合理的做法。权限验证千万别跳过我强烈建议建完账号后用下面的命令手动连一次确认权限够用且能拿到关键信息。这一步做好后面排查 exporter 连接问题的时候能省掉一大半的猜测。mysql -h 192.168.1.10 -u mysqld_exporter -p -e SHOW GLOBAL STATUS; SHOW VARIABLES LIKE server_uuid;如果这条命令执行正常能看到一大串状态变量和配置项说明账号权限没问题。如果报 Access denied 或 PROCESS 权限拒绝回到上一步仔细检查授权语句。3.3 mysqld_exporter 的安装与配置几个容易踩的坑exporter 部署位置其实有讲究。理想情况下应该部署在 MySQL 实例所在的机器上这样连接走 socket 或者回环地址即可不经过网络层安全性和稳定性都更好。如果实例太多没法一台台部署也可以集中部署然后通过网络连接但每新增一台实例就要同步改配置维护成本会更高。我的做法是跟随实例部署一台 MySQL 配一个 exporter本地以 systemd 服务方式托管。exporter 的运行方式并不复杂二进制文件加了几个必选参数。我用的是通过文件方式加载数据库凭证避免命令行暴露密码。需要预先创建一个包含用户名和密码的配置文件然后 exe 启动时通过参数指定这个文件的位置同时再指定数据源名称。这里要求 MySQL 账号密码写在 DSN 中整体结构类似 URL 的格式。exporter 本身通过参数指定监听端口默认是 9104。服务托管方面写一个 systemd service 文件指定用户、启动命令再加上 service 文件本身的管理和重载步骤。需要注意 exporter 用什么系统用户跑一般建议不要用 root而是单独建一个低权限用户比如 prometheus。服务配置里再设置进程重启策略让 exporter 崩溃后自动拉起。配置完后用一个临时命令验证指标接口是否正常工作。从接口返回的信息中过滤一下关键词如果能看到很多以 mysql_ 开头的指标说明采集器工作正常数据也已经成功暴露出来了。端口连通性也要确认否则 Prometheus 拉不到数据时无法判断是端口没有监听还是被防火墙挡住了。提示mysqld_exporter 默认只开启部分采集器。如果只按默认配置跑你会拿到一部分基础指标但 InnoDB 相关的重要指标是缺失的。配置文件中通过 collector 开关来控制采集项需要什么指标就开对应的采集器一个经典的收集场景是开启 InnoDB、status 和 variables 这几个核心项。特别是处理复杂 SQL 的业务库innodb 相关的缓冲池命中率、锁等待、日志写入情况这些才是排查性能问题的关键数据。3.4 Prometheus 接入与指标验证确认数据真的拉过来了Prometheus 拉取目标是在主配置文件中的 scrape_configs 段定义的。新增加一个 job 来描述 MySQL 监控目标的采集方式并指定目标的地址和端口。这里每个目标地址就是部署了 exporter 的那台机器整体配置并不复杂。配置完成后需要先校验配置文件语法Prometheus 专门提供了命令行检查工具直接传入配置文件即可。如果没有输出错误信息说明配置语法是正确的。接下来重新加载配置让新增加的抓取任务生效。需要注意的坑是Prometheus 默认的抓取超时时间和间隔如果 MySQL 实例很多或者单实例指标量大一个抓取周期内可能拉不完需要在全局配置或 job 级别调整这些时间参数。我当时几十个实例的抓取用了默认参数但单台慢查询很多的实例确实出现过抓取超时的情况只有长时间观察并调整参数后才稳定。验证拉取是否正常有很直观的办法在 Prometheus 的查询框里输入一个指标名点执行后如果能看到数据表和图表说明数据链路是通的。这里需要特别确认的是第一指标有没有值第二up 指标有没有达到预期结果。通过表达式查询当前实例的存活状态只有当值为 1 时才表明抓取正常。这个验证步骤不能跳因为它既验证了 Prometheus 到 exporter 的链路也验证了 exporter 到 MySQL 的链路是整个监控能否真正发挥作用的前提。4. 告警规则让监控从看板变成值班4.1 哪些指标值得第一时间盯住监控面板搭起来之后很多人会陷入什么都想看的误区把几十个指标全部堆上去结果真正的故障反而被海量信息淹没了。我个人的观点是告警规则宁可少而精也不要滥而杂。真正值得第一时间盯着看的就这几类实例存活状态包括进程是否挂了、端口是否通、采集是否正常。这是最底层的兜底任何异常都得先从这里暴露。MySQL 存活与连接状态数据库进程是否存活、当前连接数占最大连接数的比例。连接数打满时通常会伴随雪崩这个指标要配上高优先级告警。复制异常主从复制是否在跑、复制延迟是多少、从库 SQL 线程有没有报错。复制状态异常往往是数据一致性出问题的先兆也是最容易延迟发现的故障。慢查询与性能核心指标慢查询数量的增长速度、InnoDB 缓冲池命中率、临时表落盘数量、锁等待时间。这些指标正常与否直接反映了 SQL 质量和数据库健康度。磁盘与容量趋势磁盘使用率、binlog 文件总体积的增长趋势、InnoDB 数据文件大小。磁盘满是非计划停机的大概率原因而容量问题用百分比阈值很难防住结合增速预测会可靠很多。一行关于如何选择阈值的建议不要照抄网上现成的阈值你的库和别人的库在硬件规格、业务压力、数据规模上都不一样只能拿自己正常运营一段时间的数据做基准然后在这个基准上浮动成阈值。网上那些数字只能作为起点不能作为终局。4.2 告警规则文件的结构与写法Prometheus 的告警规则统一放在规则文件里通过主配置进行加载。规则文件的核心就是定义规则组每个规则组包含多条告警规则。告警规则包含告警名称、告警级别、触发条件的 PromQL 表达式、以及告警内容的模板变量。PromQL 是这套体系里最需要花时间掌握的技能。乍一看有点别扭但它本质上就是带着过滤器和聚合函数的时序查询语言。比如查询实例是否存活就是获取指标当前值然后判断是否为 0判断复制是否中断就是确认当前主从线程的运行状态值是否为 0。这些都是最基本的用法。复杂一点的查询比如计算连接数使用率需要先拿到当前连接数指标再除以最大连接数配置值然后乘以 100 得到百分比实际上就是指标之间的数学运算。PromQL 的聚合操作对多实例场景特别有用一个表达式可以把所有实例的指标汇总成一条线一眼看出全局状态。规则文件里普遍需要慎重对待的是 for 参数。它表示条件持续多久才触发告警这个参数能避免瞬时抖动造成的误报。比如磁盘使用率超过 85% 持续 5 分钟才触发比一超过阈值就报警科学得多。for 设置太短会频繁收到噪音告警值班同事会慢慢忽略设置太长又会延迟发现真实故障需要结合业务容忍度来权衡。告警规则写好后同样需要校验语法Prometheus 提供了专门的检查命令返回成功后再向服务端发送重载信号。规则是否生效可以直接在告警管理页面看到结果。刚开始全配置完后规则列表里 INACTIVE 状态是正常的因为条件还都没触发等真实故障或者自测压测时状态会从 INACTIVE 跳到 PENDING再变为 FIRING。4.3 复制监控的三个核心指标对 MySQL 来说复制状态监控是整个监控体系里优先级最高的部分一旦主从复制出现问题主库仍然正常对外提供服务业务感知不到异常但数据已经在悄悄产生差异。等发现问题时往往已经很晚了。复制相关的核心指标有三个我建议无论如何都要配齐。mysqld_exporter 提供的复制状态指标用来判断 IO 线程和 SQL 线程的运行状态SQL 线程失效时几乎可以断定复制已经中断。通过该指标可以精确区分来源只有其中一个为 0就是对应的线程中断两个线程正常而延迟依然很高就要看下面的秒级延迟指标。复制源位置位点这个指标用于更精细的延迟判断它表示从库已经执行到主库哪个 binlog 位置了。实际情况中主库和从库的位点之间还有差异这个差异的秒数可以更真实地反映复制延迟。组合使用三个指标才能完整描述复制的健康状态。我用一个实际的案例来说明为什么只看某一个指标会误判。某次从库的延迟告警频繁触发查复制状态线程都是正常的位点也在前进看起来一切正常。后来抓了两边指标对比发现从库执行位点和主库当前位点的差距虽然在缓慢缩小但主库的写入压力太大新产生的 binlog 比从库消费的速度快得多。这种情况单一指标根本看不出来三个指标一起看才能还原全貌。5. 可视化实战Grafana 里把数据库画成仪表盘5.1 数据源接入与仪表盘选型Grafana 本身不存监控数据它只是把 Prometheus 的数据源接进来做展示。接入数据源的过程实在没什么可说的数据源类型选择 Prometheus地址填 Prometheus 的 HTTP 接口地址保存并测试连通后就可以用了。如果出现连接失败优先检查网络连通性和地址是否正确这两步占排查原因的八成以上。仪表盘这块我需要多说两句。网络上有大量现成的 MySQL Dashboard建议不要直接导入就用。我的做法是拿一份社区比较流行的 JSON 作为基础模板然后把不适合自己场景的面板删掉再补充自己关心的面板一点一点改造成自己的。完全从零开始画面板其实也不难但效率不高基础模板能帮你把变量定义和常用 PromQL 骨架都搭好。仪表盘里最值得花心思的是变量的使用。在面板查询中写死实例地址的做法会让仪表盘完全失去复用性。正确的做法是在仪表盘设置里定义变量比如用采集指标的 job 变量和实例变量然后查询语句用变量去替换写死的部分。这样切换不同的实例或者只看某台机器的数据都只需要在上方下拉框里操作根本不需要改动图表。5.2 核心面板的高价值配置技巧面板的配置核心在于两点第一PromQL 查询要准确反映你想看的指标第二图表的展示方式要让人一眼看懂。举几个我实际在用的面板作为参考连接数面板。很多模板直接画连接数绝对值但我更建议画使用率当前连接数除以最大连接数再乘以 100这样所有实例可以在同一张图上对比有没有接近瓶颈一眼就看得出来。用实例作为图例变量来区分不同机器某台机器使用率 90% 以上时图表曲线会直观地顶到天花板位置。InnoDB 缓冲池命中率面板。命中率高说明大部分数据页都能从内存里拿到不需要访问磁盘性能就比较好。这个指标计算公式是命中次数的速率除以总读取次数的速率再乘以 100。用速率而不是直接拿计数器做除法是因为计数器是累加值直接拿当前值相除没有任何意义。这一点是所有带 counter 属性的指标做面板时都适用的原则必须用 rate 函数先转成速率。慢查询数量面板。慢查询本身是一个计数器直接画当前值的意义不大画它的增速才有价值。用速率函数算出每秒新增多少慢查询再叠加一个趋势线业务上线后的慢查询趋势直接决定了要不要安排 SQL 优化。复制延迟面板。直接把复制状态指标和延迟指标画在一起用不同的图例颜色区分。主从复制中断时曲线会直接跳到很高的值或者变成空值配合告警规则问题一出现就能在面板上看到信号。实践心得Grafana 面板不是越多越好一个仪表盘打开的时候人的注意力其实只能同时处理有限的曲线。太多了反而不知道该看哪里我们在实际使用中逐步精简最终保留下来的核心面板数量并不多但每一个都能在故障时给出明确信号。5.3 告警通知把异常推给真正该知道的人告警规则触发后如果不通知人那和没配告警没有区别。Alertmanager 就是用来打通 Prometheus 和通知渠道的组件。它的核心概念有三个分组、抑制、静默。分组是把同类告警合并成一条通知否则一次故障几十台实例同时告警人手一部手机就不停响抑制是当某个高优先级告警触发时自动屏蔽由它衍生的低优先级告警避免告警风暴静默用于在已知的维护窗口期内主动屏蔽某些告警。Alertmanager 接收 Prometheus 推送告警这个事情在 Prometheus 启动参数中指定 Alertmanager 地址即可。但实际配置时要注意Prometheus 发送的是告警触发事件到 Alertmanager由 Alertmanager 根据路由规则决定发送给哪个接收者再调用相应的通知接口。所以 Alertmanager 的配置文件核心包括路由树、接收者以及每个接收者下的通知实现细节。比如路由树定义了告警级别为紧急的走某个接收者级别为普通的走另一个接收者不同的告警交给不同的人处理这才是合理的分级策略。告警通知的接收方式上我们团队内部用的是企业微信和邮件。实际上 Alertmanager 底层通过 webhook理论上任何能收 HTTP 请求的接口都能接。配置过程中最大的坑是模板渲染失败通知内容里如果引用了不存在的告警标签整条通知会发送失败或者发出去的内容是空壳。调试告警通知最好直接触发一个真实告警来验证不要只看 Alertmanager 的控制台显示已发送就完事。6. 常见问题与排查技巧记录6.1 一张速查表解决高频问题下面把我这段时间遇到过的典型问题整理出来。遇到问题时别慌按表格里的方向逐项排查大部分问题很快就能定位。现象可能原因排查方向与解决Prometheus 的 up 指标为 0exporter 未启动、端口未监听、网络不通检查 exporter 进程、端口、防火墙与抓取配置exporter 连接 MySQL 报认证错误监控账号密码错误、网段限制、认证插件不兼容手动用 mysql 客户端连接验证确认权限和认证方式必要时升级驱动部分 mysql_ 指标缺失采集项未开启exporter 默认配置不完整修改 exporter 配置启用所需采集项重启服务复制相关指标为空或为 0监控账号没有 REPLICATION CLIENT 权限或实例本身不是从库确认账号权限排除非从库实例的误报告警一直显示 PENDING条件持续时长未达到 for 参数要求在规则文件中拉长或缩短 for 参数重新加载规则告警通知发送失败Alertmanager 路由配置错误、模板引用了不存在的标签、通知接口不可达检查 Alertmanager 日志验证模板变量手动测试通知接口Grafana 面板无数据数据源配置错误、PromQL 查询使用不对、面板变量为空先在 Prometheus 里执行相同查询验证数据源测试连通性检查变量过滤6.2 一些建议与经验心得最后总结几条经验不一定都写在文档里但都是实际踩坑后攒下来的。第一版本兼容性要心里有数。Prometheus、exporter、Grafana 各自的版本更新节奏不同我遇到过 exporter 老版本不支持新版本 MySQL 的某个状态变量导致部分指标一直为空。更新 exporter 到官方最新稳定版能省掉很多兼容性烦恼。第二抓取频率和存储保留期要提前规划。默认的 15 秒抓取间隔在大部分场景够用但指标量很大、长期存储的话时间序列数据膨胀得很快。我给不同环境的 Prometheus 设置了不同的保留期测试环境保留两周生产环境保留一个月超过期限的数据自动清理避免磁盘撑爆。第三mysqld_exporter 的配置不是越全越好。每个额外开启的采集器都意味着更多的 SQL 查询和更大的指标量。某次我一股脑把所有采集器全开结果 exporter 本身成了数据库的压力来源每次抓取要执行大量 SHOW 命令。按需开启够用就好。第四告警阈值一定基于自己数据的分布来定。新搭建的监控系统前两周不要急着配告警先让 Prometheus 收集数据观察正常业务下的指标波动范围再根据这个范围设置阈值。我见过不少团队直接把网上的阈值配上去结果告警一天响几十次最后所有人对告警彻底麻木。第五监控系统的可用性本身也要兜底。Prometheus 挂掉了监控就成瞎子。给 Prometheus 服务端也配上进程级别的守护和端口存活检测有条件的加上另一个监控节点做交叉检测。至少要做到 Prometheus 挂了还能有人被通知到。我个人在实际维护中的体会是MySQL 监控体系的建设不是一劳永逸的活随着业务增长新的指标需求、新的告警策略、新的面板展示方式都会不断出现。把这套基础设施搭好后续的调整和扩展就有了稳固的地基。希望这篇踩坑记录能让你少走一些弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑