show databases权限只能在.全局范围授予,不能用于库级或表级;语法上on dbname.*不报错但无效,权限不会写入系统表,执行show databases仍报错error 1227。

SHOW DATABASES 权限只能在 *.* 全局范围授予
MySQL 不允许把 SHOW DATABASES 当作库级或表级权限来授。你写 GRANT SHOW DATABASES ON mydb.* TO 'u'@'%' 语法上不报错,但权限根本不会写入系统表——查 SHOW GRANTS FOR 'u'@'%' 看不到它,执行 SHOW DATABASES 依然报 ERROR 1227 (42501): Access denied; you need (at least one of) the SHOW DATABASES privilege(s)。
真正有效的写法只有一种:GRANT SHOW DATABASES ON *.* TO 'username'@'host'。这里的 *.* 是强制要求,不是占位符。
- 主机名必须完全匹配:授权了
'dev'@'192.168.1.%',但连接用的是'dev'@'localhost',权限不生效 - MySQL 8.0+ 中若用户绑定了角色,需确认该角色已激活(
SET ROLE ALL),否则权限不继承 - 旧版本(如 5.7)建议执行
FLUSH PRIVILEGES;新版本通常自动刷新,但部署特殊时仍可能卡缓存
授完权还看不到库?先验证这三件事
常见现象是命令执行成功,但用户登录后 SHOW DATABASES 仍为空或报错。这不是权限没给,而是环境链路断了:
- 执行
GRANT的账户本身没有GRANT OPTION,或不是SUPER/SYSTEM_USER角色——权限语句会静默失败 - 用户存在但主机名不一致:
SELECT User, Host FROM mysql.user WHERE User = 'username'确认实际注册的 host 是什么 - MySQL 启用了
skip-show-databases配置项(my.cnf 中),此时任何GRANT都无效,必须改配置并重启
为什么给了 SELECT on mysql.db 还不行?
有人试过给用户 SELECT 权限在 mysql.db 表上,以为能绕过 SHOW DATABASES 限制,结果发现 SHOW DATABASES 依旧失败。这是因为:
-
SHOW DATABASES的行为由全局权限控制,和底层系统表访问权限完全解耦 -
mysql.db存的是「某个用户对某库的权限」,不是「所有库的列表」;它不参与SHOW DATABASES的输出逻辑 - 即使你
SELECT * FROM mysql.db能查出一堆库名,MySQL 也不会因此让SHOW DATABASES返回它们
开发账号要不要默认开 SHOW DATABASES?
不要。这是最容易被忽略的安全盲区:
- MySQL 从 5.7 开始就把
SHOW DATABASES设为独立权限项,目的就是防信息泄露 - 多租户场景下,一个开发账号看到
tenant_a_prod、tenant_b_staging这类库名,等于暴露了其他客户的环境结构 - 有 CREATE/DROP 权限的账号会“间接可见”部分库名,但这属于不稳定副作用,不能当作策略依赖
真正可控的做法,是按需授予 SHOW DATABASES,且仅限必要人员——它控制的不是数据访问,而是服务器拓扑可见性。











