如果你在MySQL里为审计账号只配置了SELECT ON *.*,却发现连performance_schema都无法访问,别急着怀疑操作失误——这不是你手抖,而是MySQL权限体系本身存在一个常见陷阱。
由于performance_schema属于“伪库”,权限必须逐一显式授予具体表(如events_statements_summary_by_digest),无法使用
ON performance_schema.*进行批量授权,且默认情况下不包含在GRANT SELECT ON *.*覆盖范围内。

为什么只给 SELECT 权限仍无法连接 performance_schema?
第三方审计工具(例如 Prometheus + mysqld_exporter、Percona Monitoring,或自研采集脚本)通常需要读取 performance_schema 和 information_schema 中的数据。但问题在于,这两个库并不属于常规数据库的权限体系。即使你执行了 GRANT SELECT ON *.*,MySQL 依然会默认拒绝访问 performance_schema——因为它是一个“伪库”,权限必须逐表显式授予,并且不支持使用 ON performance_schema.* 这种批量方式。你猜怎么着?许多新手都在这里卡住。
将 GRANT SELECT 应用到具体表,而非整个库
审计系统真正需要的是那几张高价值的统计表,而非整个 schema。盲目授予 performance_schema.* 权限不仅会暴露线程堆栈、SQL 文本、锁等待链等敏感信息,而且在 MySQL 8.0+ 中会直接报错拒绝该语法,根本没有商量余地。那么,实际应该如何授权?
GRANT SELECT ON performance_schema.events_statements_summary_by_digest TO 'auditor'@'%';(必授,用于查看 SQL 执行频次与指纹)GRANT SELECT ON performance_schema.events_waits_summary_global_by_event_name TO 'auditor'@'%';(必授,用于全局等待事件聚合)GRANT SELECT ON information_schema.TABLES TO 'auditor'@'%';(可选,仅当工具需要自动发现表时)GRANT SELECT ON information_schema.STATISTICS TO 'auditor'@'%';(可选,用于查询索引分布)
注意:performance_schema.threads 或 processlist 千万不要授权——它们包含当前正在执行的 SQL 文本,属于高危泄露点,能避则避。
认证插件和 host 匹配是隐形断连点
即使权限全部授予,pymysql、mysqlclient 或某些旧版 exporter 仍可能报错 Access denied for user。此时不要急着查权限,问题往往出在认证层不兼容:
- MySQL 8.0+ 默认使用
caching_sha2_password,而大多数审计 agent 仍依赖mysql_native_password这种老旧的插件。 - 因此创建账号时必须显式指定:
CREATE USER 'auditor'@'10.20.30.%' IDENTIFIED WITH mysql_native_password BY 'xxx'; - 还需要确认审计服务器的真实出口 IP 是否匹配 host 模式。如果走 Kubernetes Service 或云负载均衡,可以使用
SELECT SUBSTRING_INDEX(USER(), '@', -1);查看实际连接来源,否则很容易被 host 规则拦截。
视图封装不适用于 performance_schema
有人会想:能否通过视图将 events_statements_summary_by_digest 的字段裁剪后,再授权给审计账号,这样既安全又灵活?想法很好,但行不通——MySQL 不允许在 performance_schema 上创建视图,会报错 ERROR 1356 (HY000),也不支持设置 SQL SECURITY DEFINER。所有授权必须直接落在原始表上,且无法进行字段级控制。这意味着你必须信任审计工具不会滥用字段,或在应用层自行过滤结果。安全与便利之间,总得找个平衡点。
