为什么在MySQL中执行GRANT ALL PRIVILEGES命令会提示语法错误?

作者:袖梨 2026-08-11

GRANT ALL PRIVILEGES 报语法错误主因是语句不合法:MySQL 8.0+ 禁止 GRANT 中使用 IDENTIFIED BY,须先 CREATE USER;库名含数字或特殊字符时必须用反引号包裹;WITH GRANT OPTION 需显式声明且仅在其权限作用域内生效。

GRANT ALL PRIVILEGES 报语法错误,绝大多数情况不是权限问题,而是语句本身在当前 MySQL 版本下根本不合法——尤其当你用了 IDENTIFIED BY 或库名含数字时。


MySQL 8.0+ 不允许 GRANT 里带 IDENTIFIED BY

你写的这句:GRANT ALL PRIVILEGES ON *.* TO 'u'@'%' IDENTIFIED BY 'pwd' WITH GRANT OPTION;,在 MySQL 8.0 及以后版本会直接报 ERROR 1064 (42000)

原因很明确:账户创建和权限分配被拆成两个独立操作。密码、认证插件这些属于用户身份属性,必须由 CREATE USERALTER USER 处理。

  1. 用户不存在?先跑:CREATE USER 'u'@'%' IDENTIFIED BY 'pwd';
  2. 用户已存在?改密码用:ALTER USER 'u'@'%' IDENTIFIED BY 'newpwd';
  3. 再授予权限:GRANT ALL PRIVILEGES ON *.* TO 'u'@'%' WITH GRANT OPTION;
  4. 最后建议加一句:FLUSH PRIVILEGES;(尤其批量操作后或跨客户端生效慢时)

库名是数字或含特殊字符时必须加反引号

RDS 或本地 MySQL 都一样:如果数据库名是纯数字(比如 12345)、含中划线(my-db)或刚好撞上关键字(order),不加反引号就解析失败。

错误写法:GRANT SELECT ON 12345.* TO 'u'@'%'; → 直接报语法错

正确写法:GRANT SELECT ON `12345`.* TO 'u'@'%';GRANT SELECT ON `my-db`.* TO 'u'@'%';

注意:` 是英文键盘左上角那个键(Esc 下面),不是单引号 '

WITH GRANT OPTION 不是默认附带的

GRANT ALL PRIVILEGES 本身不包含转授权限。没加 WITH GRANT OPTION,哪怕你是 root 执行的,被授权用户也执行不了任何 GRANT 语句。

常见现象:

  1. SHOW GRANTS FOR 'u'@'%'; 输出里看不到 GRANT OPTION
  2. 该用户一执行 GRANT SELECT ON db.t TO ... 就报 ERROR 1045

要开转授,必须显式加上,并且作用域要匹配:

  1. 全局转授:GRANT ALL PRIVILEGES ON *.* TO 'u'@'%' WITH GRANT OPTION;
  2. 仅某库内可转授:GRANT SELECT, INSERT ON `app_db`.* TO 'u'@'localhost' WITH GRANT OPTION;
  3. 别指望“多个 GRANT 语句自动合并 GRANT OPTION”——它只绑定在当前那条语句的权限范围上

连接能通但 GRANT 报错,可能是认证插件不兼容

即使 CREATE USERGRANT 全对,FLUSH PRIVILEGES 也执行了,仍连不上或卡在认证阶段?大概率是 caching_sha2_password 插件惹的祸。

旧客户端(如老版 PHP mysqli、某些 JDBC 驱动、Navicat 旧版本)不支持这个默认插件,握手直接断开,表现就是 Access denied,但用户名密码完全没错。

临时解法(兼容性优先):

  1. ALTER USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
  2. FLUSH PRIVILEGES;

长期建议升级客户端或驱动,而不是降级认证方式。

真正容易被忽略的是:GRANT 的作用域和 WITH GRANT OPTION 的绑定关系是静态的、不可继承的。给一个用户 SELECT ON db1.* + WITH GRANT OPTION,他不能拿这个权限去授予 db2 的任何东西,也不能授予 CREATE TABLE ——哪怕你后续给他加了那个权限,转授开关也不自动打开。

相关文章

精彩推荐