SHOW DATABASES可见性由user表中show_db_priv字段控制,非GRANT语法授权;设为N后用户仅见其被显式授过权(含USAGE)的数据库,修改需UPDATE mysql.user并FLUSH PRIVILEGES。

普通用户执行 SHOW DATABASES 默认能看到所有数据库名,这不是权限漏洞,而是 MySQL 的默认行为——它不靠 GRANT 控制库名可见性,而靠 show_databases 全局权限开关。想让普通用户只看到自己有权限的数据库,必须关掉这个全局开关。
show_databases 权限本质是全局开关,不是 GRANT 授权项
MySQL 没有 GRANT SHOW DATABASES ON db1.* TO 'user'@'host' 这种语法。show_databases 是 user 表里的一个布尔字段(show_db_priv),属于全局权限位,和 select_priv、insert_priv 同级。只要该字段为 Y,用户就能看到全部库名;设为 N 后,用户只能看到自己拥有任意权限的数据库(哪怕只有 USAGE 权限)。
- 它不随具体数据库授权动态变化,只在用户连接时读取一次
- 修改后必须
FLUSH PRIVILEGES或重启 mysqld 才生效(取决于版本) -
root用户默认为Y,普通用户新建时默认也是Y
关闭 show_databases 权限的实操步骤
直接更新 mysql.user 表最稳妥,避免用 GRANT 语句误操作(因为 GRANT 不支持改这个字段):
UPDATE mysql.user SET show_db_priv = 'N' WHERE user = 'your_user' AND host = '%';<br>FLUSH PRIVILEGES;
- 务必指定
host,否则可能批量误改多个同名用户 - 确认改的是目标用户:
SELECT user, host, show_db_priv FROM mysql.user WHERE user = 'your_user'; - 如果用户已存在且有其他权限,不要用
DROP USER + CREATE USER重建,会丢失原有授权
用户仍看不到自己有权限的库?检查权限粒度是否足够
关掉 show_databases 后,用户只能看到“自己被显式授过权”的库。但注意:MySQL 判定“有权限”不是看能否查数据,而是看 user 表或 db 表里是否有对应记录。
- 只执行过
GRANT SELECT ON db1.* TO 'u'@'%'→ 可见 db1 - 只执行过
GRANT USAGE ON db1.* TO 'u'@'%'→ 也可见 db1(USAGE 表示“占个坑”,无实际操作权限但满足可见条件) - 没对任何库执行 GRANT,只创建了用户 → 连
information_schema都看不到(除非显式GRANT USAGE ON *.*) - 若用
GRANT ... ON *.*授权,会导致用户又看到所有库名(因为匹配了全局权限位)
容易被忽略的兼容性细节
MySQL 8.0+ 默认启用 skip-show-database 配置项(在 my.cnf 中),但它只限制未授权用户执行 SHOW DATABASES 报错,不改变已授权用户的可见范围。真正起效的是 show_db_priv 字段本身。
- MySQL 5.7 和 8.0 对该字段行为一致,但 8.0 新增了角色机制,可通过角色间接控制,不过底层仍是改这个字段
- 某些云厂商 RDS(如腾讯云、阿里云)会禁用直接改
mysql.user表,需走控制台或 API 设置“隐藏数据库列表”开关 - 应用连接池复用连接时,用户权限变更后新连接才生效,旧连接缓存不变











