MySQL如何授权用户访问多个指定数据库

作者:袖梨 2026-09-01

<p>必须为每个库单独执行一条GRANT语句,MySQL不支持合并授权如GRANT SELECT ONdb1.,db2. TO 'user'@'%',语法直接报错ERROR 1064;正确做法是逐条执行,且库名含特殊字符或大小写时必须用反引号包裹。</p>

必须为每个库单独执行一条 GRANT 语句,不能合并或通配“所有目标库”——这是 MySQL 权限模型的硬性规则,不是操作习惯问题。

GRANT 每个库都要写一遍,不能偷懒合并在一条语句里

MySQL 不支持类似 GRANT SELECT ON `db1`.*, `db2`.*, `db3`.* TO 'user'@'%' 这种写法。语法直接报错:ERROR 1064 (42000)。它只接受单库粒度的 ON database.* 结构。

  1. 正确做法是逐条执行:GRANT SELECT ON `db1`.* TO 'app'@'%';GRANT SELECT ON `db2`.* TO 'app'@'%';GRANT SELECT ON `db3`.* TO 'app'@'%';
  2. 哪怕权限完全一致,也得重复写三次——这不是冗余,是权限系统底层依赖 mysql.db 表中“用户+主机+库名”三元组唯一匹配
  3. 别试图用脚本生成 SQL 就省事了:生成本身没问题,但每条 GRANT 必须独立执行并确认返回 OK,不能批量粘贴进客户端一次性运行(部分客户端会静默跳过失败语句)

库名含特殊字符或大小写时,反引号不能漏

如果库名是 my-app-dbUserDBorder_2024_q3,不加反引号就会触发 ERROR 1144 (42000): Wildcard denied for database

  1. 必须写成:GRANT SELECT ON `my-app-db`.* TO 'app'@'%';,而不是 GRANT SELECT ON my-app-db.* TO ...
  2. `UserDB``userdb` 是两个不同的库名,大小写敏感性取决于文件系统和 lower_case_table_names 设置,但权限匹配时严格按你写的字符比对
  3. 通配符只在库名位置生效,且仅支持 %_,例如 GRANT SELECT ON `app_%`.* TO 'dev'@'%' 是合法的;但 GRANT SELECT ON `app%`.*(少下划线)就无效

验证权限是否真生效,别信 SHOW GRANTS FOR 'user'@'host'

SHOW GRANTS FOR 'app'@'%' 只显示你“执行过哪些 GRANT”,不代表它们都加载成功了。真正有效的权限,得用该用户自己连进去看 CURRENT_USER() 的结果。

  1. 用目标账号登录:mysql -u app -p -h your-host
  2. 执行:SHOW GRANTS FOR CURRENT_USER(); —— 注意是 CURRENT_USER(),不是 USER(),后者可能显示连接时用的账号名,而非权限匹配的实际账户
  3. 输出里必须明确出现每一行你期望的授权,比如:GRANT SELECT ON `db1`.* TO 'app'@'%'GRANT SELECT ON `db2`.* TO 'app'@'%'……缺一条,说明对应那条 GRANT 没成功(常见原因是 Host 不匹配,比如你授的是 'app'@'localhost',但实际连接用的是 'app'@'10.0.1.5'

跨库 JOIN 失败?先确认两个库的权限记录都命中了同一账号

即使 SHOW GRANTS FOR CURRENT_USER() 看起来两条都有,JOIN 仍可能被拒绝。最常忽略的点是:用户连接时的 Host 和你授权时写的 Host 不一致。

  1. 查当前连接来源:SELECT USER(), CURRENT_USER(); —— 前者是“你怎么连的”,后者是“MySQL 认为你是谁”
  2. 如果输出是 'app'@'192.168.10.22''app'@'%',说明你授的是 'app'@'%',没问题;但如果输出是 'app'@'192.168.10.22''app'@'localhost',那就说明 MySQL 匹配到了另一条更精确的记录(比如 'app'@'localhost'),而这条记录没被授予第二个库的权限
  3. 系统库如 information_schema 不走 mysql.db 表,跨库 JOIN 用到它时,需要额外显式授权:GRANT SELECT ON `information_schema`.* TO 'app'@'%';

真正麻烦的不是写多少条 GRANT,而是每条背后绑定的“用户@主机+库名”三元组必须严丝合缝。漏一个反引号、错一个 IP 段、少一次 FLUSH PRIVILEGES(虽然 5.7.6+ 后多数情况自动刷新,但某些权限变更仍需手动刷),都会让其中某条权限失效,且很难定位。

相关文章

精彩推荐