必须且仅授予select、process、replication client三项权限:select用于查询information_schema和performance_schema统计表,process用于执行show processlist获取全部会话,replication client用于执行show slave status等命令读取复制状态,缺一不可。

必须只给 SELECT、PROCESS、REPLICATION CLIENT 三项权限,其他一概不要。加多一个 SHOW DATABASES 或 ALL PRIVILEGES 就等于把数据库的门钥匙交出去,不是“更安全”,而是直接绕过最小权限原则。
为什么是这三个权限,缺一不可?
mysqld_exporter 不查业务表,只读取元数据和状态信息,但它依赖三个底层命令:
-
SELECT:访问information_schema和performance_schema里的统计视图(比如processlist、table_io_waits_summary_by_table) -
PROCESS:执行SHOW PROCESSLIST—— 没它就只能看到自己的连接,根本发现不了慢查询或锁等待 -
REPLICATION CLIENT:执行SHOW SLAVE STATUS和SHOW MASTER STATUS—— 缺了就无法监控主从延迟、IO/SQL线程状态
注意:SELECT ON *.* 默认包含 information_schema 和 performance_schema,但这两个库中部分表(如 user_privileges)含敏感信息。所以授权后应显式回收:
REVOKE SELECT ON information_schema.* FROM 'exporter'@'10.0.0.11'; REVOKE SELECT ON performance_schema.* FROM 'exporter'@'10.0.0.11';
MySQL 8+ 用户创建必须指定认证插件
MySQL 8.0 默认用 caching_sha2_password,但多数老版本 mysqld_exporter(v0.14.x 及更早)不支持,连不上时日志里不会报权限错,而是卡在 Access denied —— 实际是认证失败。
正确写法(显式绑定出口 IP + 插件):
CREATE USER 'exporter'@'10.0.0.11' IDENTIFIED WITH mysql_native_password BY 'safe_pass_2026';
关键点:
- host 写真实出口 IP,别用
'%'或主机名(DNS 失败会导致连接拒绝) - 确认监控服务实际出站地址(比如 Docker 容器内网 IP 是
172.18.0.5,但宿主机上跑的 exporter 看到的是127.0.0.1或宿主机 IP) - 云环境(如阿里云 ECS)要填公网出口 IP,不是内网地址
GRANT 语句不能只写 SELECT ON performance_schema.*
有些文档说“只要给 performance_schema 的 SELECT 权限就够了”,这是错的。因为 SHOW PROCESSLIST 和 SHOW SLAVE STATUS 属于全局命令,需要对应权限作用于 *.* 范围。
正确授权组合(顺序无关,但必须全有):
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'exporter'@'10.0.0.11'; GRANT SELECT ON performance_schema.* TO 'exporter'@'10.0.0.11';
特别注意:
- 不要加
WITH GRANT OPTION—— 监控账号不需要授予权限的能力 - 不要加
FILE、SUPER、SHUTDOWN等任意高危权限 - 执行完必须
FLUSH PRIVILEGES,否则权限不生效
验证权限是否真生效的最简方法
别等 Prometheus 报错才排查。直接用监控账号登录 MySQL,手动执行 exporter 会调的命令:
mysql -uexporter -psafe_pass_2026 -h10.0.0.11 -e "SHOW PROCESSLIST;" 2>/dev/null | head -3 mysql -uexporter -psafe_pass_2026 -h10.0.0.11 -e "SHOW SLAVE STATUS\G" 2>/dev/null | head -1 mysql -uexporter -psafe_pass_2026 -h10.0.0.11 -e "SELECT COUNT(*) FROM performance_schema.events_statements_summary_by_digest;" 2>/dev/null
三行都返回结果且无 ERROR,说明权限到位;任一失败,就按错误提示反查缺哪项权限。
最容易被忽略的是:权限给了,但 host 不匹配,或者认证插件不兼容——这两点比权限本身更常导致连接失败。











