mysql 8.0 中 public 不是真实角色,而是隐式虚拟组,本身不带任何权限;所谓“默认可查 information_schema”实为系统对 ''@'' 的显式授权,需通过 revoke select on information_schema.* from ''@'' 等方式回收,且必须 flush privileges。

MySQL 8.0 中 PUBLIC 角色到底有没有默认权限
结论很明确:PUBLIC 不是传统意义上的“角色”,而是一个隐式、不可删除的虚拟组,所有用户自动属于它。但它本身**不自带任何权限**——你看到的“默认可查 information_schema”等行为,其实是 MySQL 8.0 默认授予了 SELECT 权限给 information_schema.* 和 performance_schema.*,且这些授权对象是 ''@''(空用户名+空主机),实际生效时被映射到所有用户,包括 PUBLIC 上下文。
为什么 SHOW GRANTS FOR 'u1'@'%' 看不到 PUBLIC 相关权限
因为 PUBLIC 不是显式角色,SHOW GRANTS 只显示显式授予的权限或绑定的角色。真正影响权限叠加的是系统表中那些 User = '' AND Host = '' 的记录:
-
mysql.db表里可能有Db = 'information_schema', User = '', Host = ''的行,带Select_priv = 'Y' -
mysql.tables_priv或mysql.columns_priv同理
这类记录不会出现在 SHOW GRANTS 输出里,但会参与权限计算——这就是为什么新创建用户能直接 SELECT FROM information_schema.TABLES 却查不到来源。
如何安全回收 PUBLIC 级别的隐式权限
不能对 PUBLIC 执行 REVOKE(会报错 ERROR 3724 (HY000): Cannot revoke from role 'PUBLIC'),必须定位并撤销底层的空用户授权:
- 先查出隐式授权源:
SELECT Host, Db, Select_priv, Insert_priv FROM mysql.db WHERE User = '' AND Host = ''; - 逐项回收,例如撤销对
information_schema的访问:REVOKE SELECT ON information_schema.* FROM ''@''; - 同理处理
performance_schema和sys:REVOKE SELECT ON performance_schema.* FROM ''@'';、REVOKE SELECT ON sys.* FROM ''@''; - 执行
FLUSH PRIVILEGES;—— 这里必须加,因为修改的是系统表,REVOKE命令不作用于空用户记录
注意:回收后,所有用户(包括 root)都将失去对这些库的访问权,除非显式重新授权。某些监控工具或备份脚本可能依赖 information_schema,需提前验证。
回收后最易被忽略的兼容性问题
MySQL 8.0 默认开启 information_schema_stats_expiry(控制统计信息缓存),但若用户已无 SELECT 权限,EXPLAIN、SHOW CREATE TABLE 等依赖元数据的操作会直接报错 ERROR 1142 (42000): SELECT command denied to user,而不是静默降级。
更隐蔽的是:部分客户端(如旧版 phpMyAdmin、DBeaver)在连接后自动查询 information_schema.SCHEMATA 列出数据库列表,权限回收后会导致连接成功但无法展开数据库树——这不是连接失败,而是前端静默吞掉错误,排查时容易误判为 UI Bug。











