先说一个在 MySQL 5.7 中经常被忽略的常见坑:执行 GRANT 报错时,问题的根源往往并不在语法本身,而是操作之前漏掉了一个关键检查环节——用户到底有没有被成功创建出来。
很多人习惯性地认为 GRANT ... IDENTIFIED BY 一定能顺便把用户建好。确实,在 5.7 版本中它具备这个能力,但有一个重要前提:执行者自身必须拥有 CREATE USER 权限。如果权限不足,MySQL 会“静默”忽略掉创建用户这个动作,只尝试进行赋权操作,结果用户在 mysql.user 表里根本不存在,自然会报类似 ERROR 1141 这样的错误。

GRANT 报错前先确认用户是否存在
遇到 GRANT 报错时,第一反应不应该是去修改权限语句,而是先查一下这个账号到底有没有真正落库。常见的误区是以为只要写了 IDENTIFIED BY,MySQL 就会自动创建用户,但很多情况下它并不会——要么是执行者缺少 CREATE USER 权限,要么是当前会话连接的是从库,或者 Grant_priv 字段不是 Y。
那么,正确的验证方式是什么?
- 使用
SELECT User, Host FROM mysql.user WHERE User = 'u';进行精确查询。注意大小写是敏感的,而且'u'@'%'和'u'@'localhost'是两个完全独立的账号,缺一不可。 - 如果查不到记录,说明
GRANT ... IDENTIFIED BY确实被静默忽略了,或者根本没有生效。 - 千万不要依赖
SHOW GRANTS FOR 'u'@'%'来判断用户是否存在,因为如果用户不存在,这条命令会直接报ERROR 1141,而不是返回空结果。 - 即使查到了用户行,也要检查一下
plugin字段。如果该字段为空,或者显示auth_socket之类的插件,即使用户行存在,客户端也无法正常登录(可能会报ERROR 1524)。
为什么 GRANT 后用户仍查不到
这里有一个非常经典的场景:你使用 'admin'@'%' 这个账号执行 GRANT SELECT ON db.* TO 'u'@'%' IDENTIFIED BY 'p';,但 'admin'@'%' 本身并没有 CREATE USER 权限。MySQL 5.7 在这种情况下会静默忽略创建用户的动作,只尝试进行赋权——由于用户不存在,赋权自然失败,但离谱的是,GRANT 语句竟然返回了 Query OK。这确实是一个容易让人措手不及的误导行为。
验证起来其实很简单:执行完 GRANT 后,立刻用 SELECT User, Host, plugin FROM mysql.user WHERE User = 'u'; 查一下。如果结果为空,说明创建用户失败了。如果查到了但 plugin 字段为空或者是 unix_socket,则说明认证方式不兼容。
这种情况下,最稳妥的做法是显式分成两步操作:
- 先用
CREATE USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'p';创建用户 - 再执行
GRANT ... TO 'u'@'%';授予权限
两步分开执行,互不干扰,任何一步出错都会直接报错,不会出现静默忽略的情况。
FLUSH PRIVILEGES 是否必要
在 MySQL 5.7 中,只要你是通过 CREATE USER 或 GRANT 这类正常操作来管理权限的,FLUSH PRIVILEGES 完全不需要。它只对直接修改 mysql.user 表这种绕过权限系统的方式有效。
滥用 FLUSH PRIVILEGES 不仅多余,反而容易掩盖真实问题:
- 如果你在从库上执行它,它不会同步到主库,结果会导致主从权限不一致
- 如果权限表结构损坏(比如升级后没有运行
mysql_upgrade),FLUSH虽然会失败但不报错,让你误以为操作已经成功 - 它根本修复不了
plugin字段错误,也无法解决密码策略拦截问题(如ERROR 1819)
记住一条原则:正常操作不需要刷新权限,乱刷反而添乱。
容易被忽略的权限源头问题
即使你确认用户存在、plugin 正确、密码策略也调低了,GRANT 仍然失败——这时候大概率是执行者账号自身的权限不够。
需要重点检查以下几个地方:
- 执行
SELECT Grant_priv FROM mysql.user WHERE User = 'your_admin' AND Host = 'your_host';,结果必须为Y。 - 如果你使用的是
'root'@'%',请注意它和'root'@'localhost'是两个独立的账号。后者通常拥有完整权限,而前者可能权限受限,这一点很多人容易忽视。 - 某些云数据库(例如阿里云 RDS)默认会禁用
GRANT OPTION,即使你看到账号的权限显示ALL PRIVILEGES,实际上也无法转授权限。此时执行GRANT ... WITH GRANT OPTION必然会失败。
说到底,真正卡住你的往往不是 GRANT 怎么写,而是“谁在执行”以及“执行者自己有没有资格执行”这两个问题。弄明白这两点,比死记硬背各种语法要重要得多。
