<p>SHOW DATABASES权限是全局权限,必须用REVOKE SHOW DATABASES ON . FROM 'user'@'host'撤销;撤销后需FLUSH PRIVILEGES,且仍需配置skip-show-database并重启mysqld才能彻底屏蔽库名泄露。</p>

SHOW DATABASES 权限不是“数据库级权限”,而是全局权限
撤销 SHOW DATABASES 权限不能写成 REVOKE SHOW DATABASES ON mydb.* FROM ...——它不作用于某个库,只存在于全局范围(ON *.*)。MySQL 把它和 SELECT、INSERT 这类操作权限并列管理,但语义完全不同:它控制的是“能否列出所有库名”,而不是“能否访问某个库”。
必须用 REVOKE SHOW DATABASES ON *.* 显式撤销
直接执行这条语句才能真正关掉该权限:
REVOKE SHOW DATABASES ON *.* FROM 'dev_user'@'192.168.1.%';
-
dev_user和192.168.1.%必须与当初GRANT时的user@host完全一致,'dev_user'@'%'和'dev_user'@'localhost'是两个独立账号 - 不能省略
ON *.*,否则报错ERROR 1147 (42000) - 撤销后必须立刻执行
FLUSH PRIVILEGES;,否则已建立的连接仍能执行SHOW DATABASES
撤销后用户仍可能看到库名:INFORMATION_SCHEMA 是另一个泄露源
即使 SHOW DATABASES 被禁用,普通用户只要能连上 MySQL,就还能运行:
SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA;
这是因为 INFORMATION_SCHEMA 的访问控制独立于 SHOW DATABASES 权限。解决办法只有两个:
- 在 MySQL 配置文件(
my.cnf)中添加skip-show-database并重启 mysqld(该参数会同时限制SHOW DATABASES和INFORMATION_SCHEMA.SCHEMATA对非授权用户的可见性) - 或更彻底地:用
DROP USER删除账号,或用ALTER USER 'dev_user'@'%' ACCOUNT LOCK;锁定账号(MySQL 5.7.6+)
验证是否真生效:别只看 SHOW GRANTS
SHOW GRANTS FOR 'dev_user'@'192.168.1.%'; 只显示显式授予/撤销的权限,而 SHOW DATABASES 权限一旦被撤销,就不会出现在输出里——但你得亲自连过去试:
- 用
dev_user登录后执行SHOW DATABASES;,应返回Access denied - 再执行
SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA;,若仍能查出全部库名,说明skip-show-database没配或没重启 - 注意:应用连接池里的长连接可能缓存旧权限,测试前最好重启应用或 kill 对应连接(
KILL CONNECTION xxx;)
实际中最容易被忽略的一点是:skip-show-database 是个启动参数,改完配置不重启 mysqld 就等于没做。


















