MySQL权限分层:全局权限(如ON .)跨库生效,数据库级权限(如ON mydb.*)仅限指定库;CREATE/DROP DATABASE等元数据操作必须授予全局权限;权限检查顺序为全局→数据库→表→列,高优先级覆盖低优先级。
MySQL 的权限体系是分层的,GRANT 语句中指定的权限作用域直接决定用户能做什么。全局权限(如 GRANT SELECT ON *.*)表示对所有现有和未来创建的数据库都生效;而数据库级权限(如 GRANT SELECT ON mydb.*)只在 mydb 这个库内有效,哪怕之后新建了 otherdb,该用户也无权访问。
即使你给用户授予了 mydb 的全部权限(GRANT ALL ON mydb.*),他依然不能执行 CREATE DATABASE otherdb。因为 CREATE DATABASE 是一个需要 CREATE 全局权限的操作——它不作用于某个具体库,而是影响服务器元数据。常见误操作是以为“有了库级 ALL 就能建库”,结果报错:ERROR 1044 (42000): Access denied for user ... to database 'otherdb'。
GRANT CREATE ON *.* TO 'u'@'%' ✅ 允许创建任意新库GRANT CREATE ON mydb.* TO 'u'@'%' ❌ 不起作用,MySQL 忽略该授权DROP DATABASE、SHOW DATABASES 也都依赖全局权限如果一个用户同时拥有全局 SELECT 和某个库的 REVOKE SELECT,最终仍可查该库——因为全局权限未被显式收回,且覆盖更细粒度的拒绝。MySQL 权限检查顺序是:全局 → 数据库 → 表 → 列,只要某一层允许,就通过(除非被更上层显式拒绝)。这意味着:
REVOKE SELECT ON mydb.* 无法取消 SELECT ON *.*
SHOW GRANTS FOR 'u'@'%' 返回的结果里,*.* 条目会出现在 mydb.* 前面,反映检查顺序FLUSH PRIVILEGES 不解决权限不生效问题,真正生效靠的是权限表(mysql.user, mysql.db)的实时读取用 mysqldump --all-databases 要求用户有全局 SELECT 和 LOCK TABLES,但很多人只给了目标库权限,导致备份中途失败。更隐蔽的问题是:如果用户只有 mydb.* 权限,却尝试 mysqldump --databases mydb otherdb,MySQL 会拒绝导出 otherdb(即使它存在),并报错 Access denied for user ... to database 'otherdb' ——这不是连接问题,是权限校验在 dump 阶段逐库触发的。
mysqldump -u backup_user -p --databases mydb otherdb # 如果 backup_user 没有 otherdb.* 或 *.* 权限,这里就会中断
实际部署中,别默认“给库权限就够了”,先想清楚操作是否跨库、
