1. 从零开始:为什么你需要Mysqld_exporter?
如果你正在管理MySQL数据库,无论是单实例还是庞大的集群,心里肯定有个声音在问:“我的数据库现在到底健不康?” 是CPU跑满了,还是连接数爆了?慢查询是不是又偷偷增加了?以前,我们可能得手动登录服务器,敲一堆SHOW GLOBAL STATUS、SHOW PROCESSLIST命令,或者依赖一些不那么直观的脚本。但说实话,这种方式既累人又容易遗漏关键指标,尤其是在半夜被报警叫醒的时候,脑子一团浆糊,根本没法快速定位问题。
这时候,Mysqld_exporter就该登场了。简单来说,它是Prometheus监控生态里专门负责“打听”MySQL内部状况的“特工”。它会自动、持续地从你的MySQL实例中收集上百个关键指标——比如查询吞吐量、连接数、InnoDB缓冲池状态、复制延迟等等——然后把这些数据转换成Prometheus能理解的格式,通过一个HTTP接口暴露出来。之后,Prometheus服务器会定期来这个接口“抓取”数据,存储到时序数据库里。最终,你可以在Grafana上配置一个酷炫的仪表盘,所有数据库的健康状况一目了然。
我见过不少团队,在没上监控之前,数据库出了问题就像在黑暗中摸索,全靠经验和运气。部署了Mysqld_exporter之后,相当于给数据库装上了全方位的“体检仪”和“黑匣子”,不仅能实时看到问题,还能回溯历史数据,分析趋势。这对于保障业务稳定性、进行容量规划和性能调优,简直是质的飞跃。接下来,我就手把手带你走一遍完整的部署流程,并把那些我踩过的、以及帮别人排查过的典型“坑”都给你捋清楚,让你一次部署成功,少走弯路。
2. 实战部署:一步步把Mysqld_exporter跑起来
部署这件事,讲究的是思路清晰,一步一个脚印。最怕的就是东一榔头西一棒子,最后自己都搞不清配置到哪一步了。我会把流程拆解成几个明确的阶段,你跟着做就行。
2.1 第一步:在MySQL里准备好“通行证”
Mysqld_exporter不是神仙,它访问MySQL数据库也需要一个合法的账号和密码。这个账号不需要太高权限,但必须有权限读取那些我们关心的性能数据。通常,我们会专门创建一个仅用于监控的数据库用户。
首先,登录到你的MySQL服务器。这里有个关键点:这个授权操作最好在需要被监控的MySQL实例本地执行,因为很多时候我们使用的是localhost和socket连接方式,远程授权可能会遇到网络或权限验证的额外问题。
打开你的MySQL命令行,执行下面的SQL语句。你可以把用户名exporter和密码YourStrongPassword123!换成你自己喜欢的,但密码一定要足够复杂,毕竟这个账号能读取很多系统状态信息。
-- 创建一个名为'exporter'的用户,允许从本地连接,并且限制最大连接数为3(防止监控账号占用过多连接) CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'YourStrongPassword123!' WITH MAX_USER_CONNECTIONS 3; -- 授予必要的权限。这三个权限是核心: -- PROCESS: 允许查看所有进程(即`SHOW PROCESSLIST`),用于监控当前查询。 -- REPLICATION CLIENT: 允许查看主从复制状态(即`SHOW SLAVE STATUS`),对监控复制集群至关重要。 -- SELECT: 允许读取特定的信息模式(INFORMATION_SCHEMA)和性能模式(PERFORMANCE_SCHEMA)表,这是大部分监控指标的来源。 GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost'; -- 执行完后,别忘了让权限生效 FLUSH PRIVILEGES;授权完成后,强烈建议你立刻测试一下这个账号是否能正常登录。这是后续所有步骤的基础,如果这里就卡住了,后面全是白费功夫。
# 使用socket方式连接测试(假设你的socket文件在/tmp/mysql.sock) mysql -uexporter -p'YourStrongPassword123!' -S /tmp/mysql.sock # 或者使用TCP/IP方式连接测试(假设MySQL端口是3306) mysql -uexporter -p'YourStrongPassword123!' -h 127.0.0.1 -P 3306如果能成功进入MySQL命令行,并且能执行一些简单的查询如SHOW GLOBAL STATUS LIKE 'Uptime';,那么恭喜你,第一步的“通行证”已经办好了。
2.2 第二步:下载、安装与配置Mysqld_exporter
现在,我们转到要运行Mysqld_exporter的服务器上(通常就是MySQL所在的机器)。首先需要获取软件包。我习惯把它放在一个统一的目录下,比如/opt。
# 创建一个专用目录 sudo mkdir -p /opt/mysqld_exporter cd /opt/mysqld_exporter # 从Github Releases下载最新稳定版本,请替换为最新的版本号 # 你可以去 https://github.com/prometheus/mysqld_exporter/releases 查看 sudo wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.1/mysqld_exporter-0.15.1.linux-amd64.tar.gz # 解压 sudo tar xzf mysqld_exporter-0.15.1.linux-amd64.tar.gz # 为了方便管理,可以把可执行文件移动到目录根下,或者创建软链接 sudo mv mysqld_exporter-0.15.1.linux-amd64/mysqld_exporter ./接下来是核心配置文件。Mysqld_exporter默认会尝试读取当前用户家目录下的.my.cnf文件,或者通过--config.my-cnf参数指定文件。我们就在它的工作目录下创建这个文件。
sudo vim /opt/mysqld_exporter/.my.cnf文件内容如下。这里配置了两个部分[client]和[mysqladmin],确保exporter在各种检查中都能使用正确的凭证。
[client] host = 127.0.0.1 user = exporter password = YourStrongPassword123! socket = /tmp/mysql.sock [mysqladmin] host = 127.0.0.1 user = exporter password = YourStrongPassword123! socket = /tmp/mysql.sock重要提示:
socket:这个路径必须和你MySQL实例的实际socket文件路径完全一致。你可以通过登录MySQL执行show variables like 'socket';来确认。- 权限:确保这个
.my.cnf文件的权限设置得当,因为它里面包含了密码。通常设置为600(仅所有者可读可写)是安全的。sudo chmod 600 /opt/mysqld_exporter/.my.cnf
2.3 第三步:配置系统服务(Systemd)并启动
为了让Mysqld_exporter能随系统启动、方便管理,我们把它配置成系统服务。这里以现代Linux发行版普遍使用的Systemd为例。
创建服务单元文件:
sudo vim /etc/systemd/system/mysqld-exporter.service将以下内容写入文件。这里我添加了一些常用的收集器(--collect.参数),你可以根据你的MySQL版本和监控需求进行增减。
[Unit] Description=Prometheus MySQL Exporter After=network.target Wants=network.target [Service] Type=simple User=prometheus # 建议创建一个专门的prometheus系统用户来运行,更安全 Group=prometheus WorkingDirectory=/opt/mysqld_exporter # 关键启动命令: # --config.my-cnf: 指定配置文件路径 # --web.listen-address: 监听地址和端口,默认是9104,可以按需修改 # --collect. 开头的参数:启用各种指标收集器 ExecStart=/opt/mysqld_exporter/mysqld_exporter \ --config.my-cnf=/opt/mysqld_exporter/.my.cnf \ --web.listen-address=0.0.0.0:9104 \ --collect.slave_status \ --collect.binlog_size \ --collect.info_schema.processlist \ --collect.info_schema.innodb_metrics \ --collect.engine_innodb_status \ --collect.perf_schema.file_events \ --collect.perf_schema.tablelocks Restart=always RestartSec=3 StandardOutput=syslog StandardError=syslog SyslogIdentifier=mysqld_exporter [Install] WantedBy=multi-user.target注意:如果你没有创建
prometheus用户,可以将上面的User和Group改为root,但这不是最佳安全实践。创建专用用户的命令是:sudo useradd --no-create-home --shell /bin/false prometheus,并记得把/opt/mysqld_exporter目录的所有权改给这个用户:sudo chown -R prometheus:prometheus /opt/mysqld_exporter。
配置好后,就可以启动服务了:
# 重新加载systemd配置 sudo systemctl daemon-reload # 设置开机自启 sudo systemctl enable mysqld-exporter # 启动服务 sudo systemctl start mysqld-exporter # 查看服务状态和日志,这是排查问题的第一步! sudo systemctl status mysqld-exporter sudo journalctl -u mysqld-exporter -f --since "5 minutes ago"如果状态显示active (running),并且日志里没有明显的错误信息,那么基本上就成功一半了。你可以用curl命令测试一下指标接口:
curl http://localhost:9104/metrics如果能看到大量以mysql_开头的指标输出(比如mysql_global_status_uptime),那么恭喜你,Mysqld_exporter已经成功启动并连接到MySQL了!
2.4 第四步:进阶场景:一台机器监控多个MySQL实例
有时候,一台服务器上会运行多个MySQL实例(比如3306、3307端口)。你当然可以为每个实例单独部署一个exporter,但更优雅的方式是使用一个exporter进程,通过不同的数据源名称(DSN)来监控多个实例。
Mysqld_exporter从v0.13.0版本开始,支持通过环境变量DATA_SOURCE_NAME指定多个数据源,格式是用逗号分隔的DSN列表。这样你只需要运行一个exporter服务。
首先,你需要为每个MySQL实例创建对应的监控账号(参照2.1步骤)。然后,修改你的systemd服务文件,不再使用--config.my-cnf,而是通过环境变量传递DSN。
修改/etc/systemd/system/mysqld-exporter.service的[Service]部分:
[Service] ... Environment="DATA_SOURCE_NAME=exporter3306:PasswordFor3306@(127.0.0.1:3306)/,exporter3307:PasswordFor3307@(127.0.0.1:3307)/" ExecStart=/opt/mysqld_exporter/mysqld_exporter \ --web.listen-address=0.0.0.0:9104 \ --collect.slave_status \ --collect.binlog_size ... Restart=always这里有几个关键点:
- DSN格式:
用户名:密码@协议(主机:端口)/数据库名?参数。对于TCP连接,协议部分可以省略,直接写(主机:端口)。最后的/表示根数据库,?后面可以跟连接参数。 - 多个DSN:用英文逗号
,分隔,中间不能有空格。 - 移除
--config.my-cnf:当设置了DATA_SOURCE_NAME环境变量后,配置文件方式就不再生效。
重启服务后,访问http://localhost:9104/metrics,你会发现指标中会包含一个target标签,用来区分数据来自哪个实例,非常方便。
3. 避坑指南:部署中常见的典型错误与排查
部署过程很少一帆风顺,尤其是第一次。下面这些错误,都是我或者我身边的同事真金白银踩出来的坑。我把它们和排查思路都列出来,你遇到问题时可以快速对照。
3.1 错误一:权限不足(Access Denied)
这是最常见的新手错误。症状就是在exporter的日志里看到类似这样的报错:
level=error msg="Error pinging mysqld: Error 1045: Access denied for user 'exporter'@'localhost' (using password: YES)" source="exporter.go:146"排查思路:
- 核对账号密码:首先,请一字不差地检查
.my.cnf文件或DATA_SOURCE_NAME中的用户名和密码。大小写、特殊字符、空格都可能是元凶。我建议先用mysql命令行工具,使用配置文件里的凭据手动连接一次,这是最直接的验证方法。mysql --defaults-file=/opt/mysqld_exporter/.my.cnf - 检查授权主机:你创建用户时用的是
'exporter'@'localhost',这意味着只能从MySQL服务器本机连接。如果你的exporter是部署在另一台机器上(即远程监控),就需要将localhost改为具体的IP地址或%(允许任何主机,不推荐生产环境使用)。例如:'exporter'@'192.168.1.100'。 - 确认权限是否生效:执行
GRANT语句后,记得FLUSH PRIVILEGES;。也可以直接查询权限表确认:SHOW GRANTS FOR 'exporter'@'localhost'; - 检查MySQL的认证插件:特别是MySQL 8.0及以上版本,默认使用了
caching_sha2_password认证插件。一些老版本的客户端或驱动可能不支持。如果遇到问题,可以考虑将用户密码插件改为mysql_native_password:ALTER USER 'exporter'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourStrongPassword123!';
3.2 错误二:Socket文件找不到(Socket Connection Failed)
这个错误通常出现在使用socket连接方式时,日志如下:
level=error msg="Error pinging mysqld: dial unix /tmp/mysql.sock: connect: no such file or directory" source="exporter.go:146"排查思路:
- 确认socket路径:这是最直接的原因。登录MySQL,执行
SHOW VARIABLES LIKE 'socket';,看看MySQL实际使用的socket文件路径是什么。它可能是/tmp/mysql.sock,也可能是/var/lib/mysql/mysql.sock,或者在其他自定义位置。 - 修改配置文件:将
.my.cnf文件中的socket参数值修改为上面查到的正确路径。 - 检查文件权限:即使路径对了,还要确保运行Mysqld_exporter的系统用户(比如
prometheus或root)有权限读取这个socket文件。你可以用ls -l /tmp/mysql.sock查看文件属主和权限。 - 考虑使用TCP/IP连接:如果socket连接问题很棘手,一个更通用的替代方案是使用TCP/IP连接。将
.my.cnf中的socket行注释掉或删除,并确保host和port(默认3306)配置正确。同时,要确保MySQL配置(my.cnf)中的bind-address不是127.0.0.1(如果exporter在本地,可以是),或者已经允许了来自exporter所在IP的连接。
3.3 错误三:老版本MySQL的密码认证问题(Old Password Authentication)
这个错误通常发生在非常古老的MySQL版本(如5.1早期版本)或某些特定配置下。错误信息会提示你需要allowOldPasswords=1参数。
level=error msg="Error pinging mysqld: this user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN." source="exporter.go:146"问题根源:MySQL历史上存在过两种密码哈希格式:旧的16位哈希(MySQL 4.1之前)和新的41位哈希。old_passwords这个系统变量控制着密码创建的哈希格式。如果这个变量被设置为ON(或1),创建的密码就是旧的16位格式,而新版的客户端驱动(如Go-MySQL-Driver)默认可能不兼容。
解决方案有两种,推荐第二种:
方案A:修改MySQL配置(需重启或调整会话)这是从根源上解决问题,但可能影响现有其他连接。
-- 全局关闭旧密码模式 SET GLOBAL old_passwords=0; -- 或者修改配置文件my.cnf,添加 old_passwords=0,然后重启MySQL然后,必须为监控用户重新设置一次密码,以生成新的41位哈希:
SET PASSWORD FOR 'exporter'@'localhost' = PASSWORD('YourNewStrongPassword123!');方案B:在Exporter的DSN中添加连接参数(无需改MySQL)这是更安全、更推荐的方式,尤其在你不敢轻易改动老数据库配置的情况下。通过环境变量DATA_SOURCE_NAME传递带有参数的DSN。
修改systemd服务文件,使用类似下面的配置:
[Service] Environment="DATA_SOURCE_NAME=exporter:YourPassword@unix(/tmp/mysql.sock)/?allowOldPasswords=true" ExecStart=/opt/mysqld_exporter/mysqld_exporter --web.listen-address=0.0.0.0:9104 ...注意DSN的格式:用户名:密码@协议(路径)/数据库?参数=值。这里的关键就是在DSN末尾添加了?allowOldPasswords=true参数。
3.4 错误四:收集器与MySQL版本不兼容(Collector Not Supported)
这个错误不是连接问题,而是exporter启动后,在采集特定指标时抛出的。例如,你的MySQL是5.6版本,但启动参数里却包含了一个只有MySQL 5.7才支持的收集器:
level=error msg="Error scraping for collect.perf_schema.replication_group_member_stats: Error 1146: Table 'performance_schema.replication_group_member_stats' doesn't exist" source="exporter.go:171"排查思路:
- 核对收集器与MySQL版本:Mysqld_exporter的每个
--collect.参数都对应着查询特定的系统表或执行特定命令。你需要确保你启用的收集器,你的MySQL版本确实支持。上面那个collect.perf_schema.replication_group_member_stats是用于组复制的,仅适用于MySQL 5.7.17及以上版本。 - 查看官方文档:最准确的方法是查阅你所用Mysqld_exporter版本官方文档中关于收集器的说明,里面通常会注明所需的MySQL最低版本。
- 按需启用收集器:不需要一股脑启用所有收集器。只启用你关心的、并且你的MySQL版本支持的收集器。过多的收集器可能会对MySQL造成不必要的性能压力。你可以先使用最基本的几个,如
--collect.global_status、--collect.global_variables、--collect.info_schema.tables,它们通常是默认开启的。 - 从启动命令中移除不兼容的收集器:找到报错信息中提到的那个收集器参数(例如
--collect.perf_schema.replication_group_member_stats),从systemd服务文件的ExecStart行中将其删除,然后重启exporter服务。
4. 部署后验证与Grafana集成注意事项
服务启动没报错,就万事大吉了吗?远远不够。部署后的验证是确保监控真正生效的关键一步。
4.1 如何验证Exporter工作正常?
- 检查端口和进程:首先,用
ss -tlnp | grep 9104或netstat命令看看9104端口是否在监听。用ps aux | grep mysqld_exporter看看进程是否存在。 - 查看服务日志:
sudo journalctl -u mysqld-exporter -n 50 --no-pager。健康的日志应该是定期输出"Scraping metrics..."之类的信息,没有持续的level=error。 - 访问指标端点:用浏览器或
curl访问http://你的服务器IP:9104/metrics。你应该能看到大量文本格式的指标。重点检查开头几行,如果有mysql_up这个指标,并且其值为1,这表示exporter成功连接到了MySQL。如果值是0,说明连接有问题,即使下面有其他指标,那些也可能是缓存或无效数据。 - 检查Prometheus Targets:在Prometheus的Web UI(通常为
http://prometheus-server:9090/targets)中,找到你配置的Mysqld_exporter job。它的状态应该是UP。如果为DOWN,将鼠标悬停在上面会显示错误信息,这是排查Prometheus与Exporter之间网络、配置问题的最直接途径。
4.2 Grafana不出图?可能是版本兼容性“玄学”
这是另一个高频问题:Exporter和Prometheus都显示正常,数据也能抓到,但Grafana仪表盘就是不显示曲线,或者显示“No Data”。
最常见的原因:Grafana仪表盘模板与你的MySQL/Exporter版本不匹配。
- 问题本质:Grafana仪表盘中的每个图表,其实都是一个查询表达式,它基于Prometheus中特定的指标名称和标签。不同版本的Mysqld_exporter,其生成的指标名称、标签可能会发生细微变化。一个为老版本Exporter设计的仪表盘模板,可能无法正确查询新版本Exporter提供的指标。
- 解决方案:
- 寻找匹配的模板:在Grafana官方仪表盘仓库(https://grafana.com/grafana/dashboards/)搜索“MySQL”时,注意看模板的“更新日期”和“版本要求”。尽量选择更新、更活跃的模板。
- 调整Exporter版本:如果业务上允许,可以尝试将Mysqld_exporter降级到与仪表盘模板年代相近的版本。有时候,这比修改几十个图表的查询语句要快得多。
- 手动调试查询:在Grafana中,进入有问题的图表,点击“Edit”进入查询编辑器。将鼠标放在查询输入框上,它会显示当前查询到的指标列表。检查你需要的指标(如
mysql_global_status_questions)是否存在。如果不存在,可能是名称变了(比如前缀或后缀不同),你需要根据Exporter实际暴露的指标名称来修改查询。
另一个排查方向:PromQL时间范围确保Grafana右上角的时间范围选择器,覆盖了Prometheus已经抓取到数据的时间段。如果你刚部署,却把时间范围选到了“过去一周”,那肯定是没数据的。
4.3 性能与安全考量
最后,分享几个实战中的小经验,关乎稳定性和安全性:
- 控制收集频率:在Prometheus的
scrape_configs中,为MySQL job设置合理的scrape_interval(如30s)。太频繁的采集(比如5s)可能会对高负载的MySQL实例造成压力。 - 使用专用监控账号并限制连接:就像我们一开始做的,用
WITH MAX_USER_CONNECTIONS 3来限制监控账号的最大连接数,防止它意外耗尽数据库连接资源。 - 防火墙策略:Exporter的监听端口(如9104)不应该对公网开放。在安全组或防火墙中,只允许Prometheus服务器所在的IP地址访问。
- 定期更新:关注Mysqld_exporter的版本更新,新版本通常会修复bug、增加对新版本MySQL的支持、优化性能。但升级前,记得在测试环境充分验证。