判断 MySQL 用户是否拥有 GRANT OPTION,最稳妥、最直接的方法,还是查看 SHOW GRANTS FOR 的输出结果中是否包含 WITH GRANT OPTION。这个标记通常出现在授权语句的末尾,只要出现,就表示该用户在对应权限范围内具备继续授权给其他用户的能力。相比之下,mysql.user 表中的 Grant_priv 字段并不一定准确,遇到角色权限、库级生效的授权,或者权限信息尚未刷新时,都可能出现判断偏差。

SHOW GRANTS FOR 输出里有没有 WITH GRANT OPTION
这是检查 MySQL 用户是否有授权权限最直接、也最可靠的方式。MySQL 不会把 GRANT OPTION 单独作为一项独立权限显示,而是把它作为已有授权语句的后缀展示出来。
执行 SHOW GRANTS FOR 'username'@'host'(注意必须完整写出 @'host',例如 'admin'@'%' 或 'root'@'localhost'),然后逐行检查输出内容中是否出现 WITH GRANT OPTION。
- 如果看到类似
GRANT SELECT ON `app`.* TO 'dev'@'%' WITH GRANT OPTION,说明该用户对app数据库拥有SELECT的授权能力,但授权范围仅限于SELECT - 如果看到
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION,则表示该账号具备全局范围的授权权限 - 如果输出结果中完全没有
WITH GRANT OPTION,即使这个用户看起来权限很多,也依然不能把权限授予别人
为什么查 mysql.user 表的 Grant_priv 字段不准
SELECT Grant_priv FROM mysql.user WHERE User='u1' AND Host='%' 返回 'Y',并不代表当前用户一定能够直接执行 GRANT。特别是在 MySQL 8.0+ 引入并启用角色机制之后,这个字段反映的只是“是否曾被直接授予全局 GRANT OPTION”,并不会自动把通过角色继承得到的权限一并计算进去。
常见的误判场景包括:
- 用户被授予了带
GRANT OPTION的角色,但没有执行SET ROLE 'admin'激活角色,此时Grant_priv可能仍然是'N',而实际可用权限已经生效 - 用户只拥有库级别的
GRANT OPTION(例如GRANT SELECT ON db1.* TO ... WITH GRANT OPTION),mysql.user.Grant_priv依旧可能显示为'N',因为这类权限不属于全局权限 - 如果手动
UPDATE过mysql.user表,却忘记执行FLUSH PRIVILEGES,那么字段值与当前实际权限状态也可能不一致
MySQL 8.0+ 下 GRANT 失败却显示“Access denied”?先确认你是不是真有 GRANT OPTION
即使你使用的是 root 账号登录,执行 GRANT SELECT ON mydb.* TO 'u1'@'%' 时如果报出 ERROR 1045 (28000): Access denied,大多数情况下并不是密码错误或主机名不匹配,而是当前账号本身没有开启 GRANT OPTION。
可以按下面步骤排查和验证:
- 先运行
SHOW GRANTS FOR CURRENT_USER(),确认结果中是否包含WITH GRANT OPTION - 如果没有,可以补充授权:
GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION - 随后执行
FLUSH PRIVILEGES(虽然 MySQL 8.0.29+ 一般会自动生效,但手动执行一次更稳妥) - 然后再次尝试执行
GRANT—— 另外要注意,MySQL 8.0+ 不再允许在GRANT语句中直接写IDENTIFIED BY,必须先用CREATE USER或ALTER USER完成用户创建或密码设置
容易被忽略的 host 匹配细节
SHOW GRANTS FOR 'api'@'%' 和 SHOW GRANTS FOR 'api'@'localhost' 实际上是两条完全不同的查询。即使用户名相同,只要 @'host' 不一致,就可能直接报出 ERROR 1141。
排查 MySQL 用户权限时务必注意:
- 先使用
SELECT User, Host FROM mysql.user WHERE User = 'api';查出该用户完整的注册记录 - 然后把查询结果中的整条
User@Host原样复制到SHOW GRANTS FOR语句中,不要手动输入,不要改动%,也不要多加空格 - 同时要注意
'localhost'和'127.0.0.1'在 MySQL 内部会被视为不同的 host,二者权限并不互通
真正决定你是否能给别人授权的,从来不只是用户名本身,而是那一串精确到字符的 'user'@'host' 组合。少一个单引号、错一个通配符,查询不到权限、无法授权,都是很常见的问题。
