access denied执行grant时并非语句报错,而是执行者自身权限不足:缺少grant option或create user权限,或host不匹配、认证插件不兼容;必须检查current_user()权限、host范围及plugin设置。

Access denied 不是 GRANT 语句本身报错,而是你用某个用户执行 GRANT 时,该用户自身权限不足——它没被授予 GRANT OPTION 或 CREATE USER 权限,连“给别人授权”这个动作都不被允许。
执行 GRANT 的当前用户必须有 GRANT OPTION 权限
MySQL 不允许任意用户随意授予权限。哪怕你是 'admin'@'%',只要建账号时没加 WITH GRANT OPTION,执行 GRANT 就会直接报 Access denied for user 'admin'@'192.168.1.100' (using password: YES)。
- 查当前用户真实权限:
SHOW GRANTS FOR CURRENT_USER;,输出里必须含GRANT OPTION - 给已有用户补权限(需更高权限账户执行):
GRANT GRANT OPTION ON *.* TO 'admin'@'%'; - 新建带授权能力的用户:
CREATE USER 'admin'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION;
host 匹配失败导致“用户不存在”假象
报 Access denied 却提示的是目标用户(如 'app'@'10.0.2.%'),往往不是它没权限,而是你执行 GRANT 时用的登录账户本身 host 不匹配——比如你用 'root'@'localhost' 登录,却想给 'app'@'10.0.2.%' 授权,MySQL 会检查 root 是否被允许操作这个 host 范围。
- 确认登录账户的 host 是否覆盖目标范围:
SELECT User, Host FROM mysql.user WHERE User = 'root'; - 若只有
'root'@'localhost',它无法跨 host 授权;需先改 host:UPDATE mysql.user SET Host = '%' WHERE User = 'root' AND Host = 'localhost'; - 再显式赋权:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'; FLUSH PRIVILEGES; - 注意:改完
Host字段后不重赋GRANT OPTION,root仍不能跨 host 执行 GRANT
认证插件不兼容,连都连不上就别提 GRANT
你看到的 Access denied 错误信息里如果带 caching_sha2_password 或握手超时,说明根本没走到权限校验阶段——连接在认证环节就断了。MySQL 8.0+ 默认用 caching_sha2_password,但旧版 PHP/Python/JDBC 驱动不支持。
- 创建用户时强制指定兼容插件:
CREATE USER 'admin'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 别改全局
default_authentication_plugin,只针对具体用户调整更安全 - 验证是否生效:
mysql -u admin -p -h 127.0.0.1(用 IP 连,避开 localhost socket 特殊路径)
真正卡住的地方往往不在 GRANT 语法,而在执行它的那个用户——它的 host、它的 plugin、它有没有被明确授予 GRANT OPTION。漏掉其中任一环,Access denied 就会毫无征兆地出现,且错误信息完全不提示真实原因。











