mysql 8.0+禁用performance_schema访问的唯一有效方式是revoke select on performance_schema.,需先撤全局权限再执行,并同步回收sys.和information_schema.processlist权限。

REVOKE SELECT ON performance_schema.* 是唯一有效方式
MySQL 8.0+ 允许对 performance_schema 显式撤权,这是禁用普通用户访问该库的直接手段。5.7 及更早版本不支持该语法,但你当前是 8.0,所以必须走这条路径——其他方法(比如只撤 PROCESS 或改 show_db_priv)完全无效。
执行前先确认用户当前权限是否已覆盖该库:
SHOW GRANTS FOR 'app_user'@'%';
若结果中存在 GRANT SELECT ON *.* 或 GRANT ALL PRIVILEGES ON *.*,必须先撤掉全局权限,否则 REVOKE SELECT ON performance_schema.* 会被忽略。
- 先执行:
REVOKE ALL PRIVILEGES ON *.* FROM 'app_user'@'%'; - 再执行:
REVOKE SELECT ON performance_schema.* FROM 'app_user'@'%'; - 最后执行:
FLUSH PRIVILEGES;(虽 GRANT/REVOKE 通常自动刷新,但此处手动更稳妥)
撤权后,用户执行 SELECT * FROM performance_schema.threads; 会直接报错 ERROR 1142 (42000): SELECT command denied to user。
为什么只撤 PROCESS 权限不够
PROCESS 权限控制的是 SHOW PROCESSLIST 和部分系统状态查看能力,但它和 performance_schema 的访问权限完全解耦。即使你已执行 REVOKE PROCESS ON *.*,用户仍可绕过,直接查 performance_schema.threads、performance_schema.data_locks 等表——只要他有 SELECT 权限。
典型绕过场景:
- ORM 框架(如 Hibernate、Sequelize)自动探测连接状态时,可能发
SELECT THREAD_ID FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' - 监控脚本误用账号执行
SELECT * FROM performance_schema.events_statements_summary_by_digest,暴露所有 SQL 模板 - 应用日志打印异常堆栈时,意外包含
performance_schema查询语句,导致权限配置被反推
这些行为都不触发 PROCESS 权限检查,只走标准 SELECT 权限校验。
别漏掉 sys 库和 INFORMATION_SCHEMA.PROCESSLIST
MySQL 8.0 中,sys 库是基于 performance_schema 的视图封装,默认对所有已认证用户可读。如果没同步撤权,用户仍可通过 SELECT * FROM sys.session; 获取等效信息。
同样,MySQL ≥ 8.0.28 新增了 INFORMATION_SCHEMA.PROCESSLIST 表,它不依赖 PROCESS 权限,只要有 SELECT 就能查——默认任何有库级 SELECT 的用户都能看到全部会话。
必须补上这两条:
REVOKE SELECT ON sys.* FROM 'app_user'@'%';REVOKE SELECT ON INFORMATION_SCHEMA.PROCESSLIST FROM 'app_user'@'%';
注意:第二条仅在 ≥ 8.0.28 有效;低于此版本执行会报错,可跳过。
验证是否真生效,不能只看 SHOW GRANTS
SHOW GRANTS 只显示显式授予/回收的权限,不反映隐式继承或缓存残留。真正可靠的验证方式是切换用户实测:
- 用目标用户登录:
mysql -u app_user -p -h db.example.com - 执行:
SHOW DATABASES;—— 应只列出业务库 +information_schema+performance_schema(系统库名始终可见,但内容不可读) - 执行:
SELECT COUNT(*) FROM performance_schema.threads;—— 必须报错,不能返回数字 - 执行:
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST LIMIT 1;—— 在 8.0.28+ 应报错或返回空;低版本可能返回一行(仅自己),但字段值应大量为NULL
最容易被忽略的是连接池复用:应用若长期复用连接,旧连接可能仍持有未刷新的权限缓存,需重启应用或等待连接重建才能体现变更。











