MySQL 8.0.12+ 支持 REVOKE SELECT ON INFORMATION_SCHEMA.* FROM 'user'@'%' 显式撤权,此前版本不支持;必须先执行该语句再授业务权限,否则元数据仍可被动态推导。

MySQL 8.0+ 中 REVOKE SELECT ON INFORMATION_SCHEMA.\* 实际有效
MySQL 8.0.12 起,REVOKE SELECT ON INFORMATION_SCHEMA.* FROM 'user'@'%' 是真正生效的权限控制手段。此前版本(如 5.7)该语句会报错或被忽略,但 8.0+ 已支持对 INFORMATION_SCHEMA 显式撤权。
常见错误现象:执行完 REVOKE 后仍能查 INFORMATION_SCHEMA.TABLES —— 很可能用户之前被授予了目标业务库的 SELECT 权限,而 MySQL 会基于“可访问的库”动态生成 INFORMATION_SCHEMA 的可见行;只要没显式撤掉元库权限,就默认可读其子集。
- 必须在授业务权限前,先执行
REVOKE SELECT ON INFORMATION_SCHEMA.* FROM 'user'@'%' - 如果用户已存在且历史权限混乱,建议先
REVOKE ALL PRIVILEGES ON *.* FROM 'user'@'%'彻底清空,再逐项授权 -
FLUSH PRIVILEGES不需要——GRANT/REVOKE操作本身即刻生效
为什么 skip-show-databases 比单纯撤 INFORMATION_SCHEMA 权限更关键
skip-show-databases 是 my.cnf 中的启动参数,它让非 super 用户调用 SHOW DATABASES 时返回空结果,连库名都看不到。这比限制 INFORMATION_SCHEMA 更底层:没有库名,就无法构造 SELECT ... FROM some_db.some_table,元数据探测直接断链。
容易踩的坑:
- 该参数仅影响
SHOW DATABASES和INFORMATION_SCHEMA.SCHEMATA的可见性,不影响已授权库内的表查询 - 修改后必须重启 MySQL 才生效,不是 SET GLOBAL 可动态调整的变量
- 如果应用依赖
SHOW DATABASES做自动发现(如某些 ORM 初始化逻辑),会出错,需提前确认
GRANT USAGE ON *.* 是安全建号的第一步,不是摆设
直接 GRANT SELECT ON app_db.users TO 'u'@'%' 可能失败(MySQL 8.0+ 报 ERROR 1410),因为用户未预创建;而先 CREATE USER 再 GRANT,中间若无过渡权限,新用户连登录都做不到。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
GRANT USAGE ON *.* 提供的是「认证通过但零操作权限」状态,是唯一安全的占位方案:
- 它不赋予任何数据库操作能力,只允许连接成功
- 后续
GRANT SELECT ON app_db.*等操作叠加在其上,不会意外继承全局权限 - 避免脚本中漏写
REVOKE导致残留mysql.user或performance_schema访问权
别信“没授权就能防住元数据”——低版本 MySQL 必须手动关
MySQL 5.7 及更早版本默认允许普通用户查 INFORMATION_SCHEMA,且 REVOKE SELECT ON INFORMATION_SCHEMA.* 语法不支持。这时唯一办法是:在创建用户时严格限定其可访问的数据库范围,并配合应用层约束。
实操要点:
- 确认版本:
SELECT VERSION();,5.7 用户必须依赖skip-show-databases+ 库级白名单 + 连接池 IP 限制三重兜底 - 不要尝试
DROP DATABASE INFORMATION_SCHEMA或改名——它是虚拟库,删不掉,还会报错 - 验证是否真生效:用目标用户登录后执行
SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES;,5.7 下应返回非零值但仅含已授权库的表;8.0+ 撤权后应报ERROR 1142 (42000): SELECT command denied
真正卡死元数据泄露的点,从来不在“能不能查某张系统表”,而在于“连有哪些库都不知道”。skip-show-databases 配合精确的 GRANT 范围,才是不可绕过的防线;其余所有权限回收,都是在补这个前提没守住之后的漏洞。

















