MySQL 8.0 中 GRANT 不再支持隐式建用户,必须先 CREATE USER 再 GRANT,否则报 ERROR 1410(禁止用 GRANT 创建用户)或 ERROR 1064(IDENTIFIED BY 语法不被识别);这是强制分离认证与授权的安全机制升级,非 bug。

MySQL 8.0 的 GRANT 语句不再支持隐式建用户,必须先 CREATE USER 再 GRANT,否则报错 ERROR 1410 (42000) 或 ERROR 1064 (42000)。
为什么 GRANT ... IDENTIFIED BY 在 MySQL 8.0 会报错
MySQL 8.0 移除了 GRANT 中的 IDENTIFIED BY 子句语法。这不是 bug,而是安全机制升级:用户身份创建(认证)和权限分配(授权)被强制拆成两个独立步骤。
- 旧写法(5.7 可用,8.0 直接报错):
GRANT SELECT ON mydb.* TO 'u'@'%' IDENTIFIED BY 'pwd'; - 新写法(8.0 唯一合法路径):
CREATE USER 'u'@'%' IDENTIFIED BY 'pwd';→GRANT SELECT ON mydb.* TO 'u'@'%'; - 报错
ERROR 1410表示当前账户无权“在授予权限时顺便建用户”,哪怕你是root;报错ERROR 1064是语法解析失败,因为服务器根本不认识IDENTIFIED BY出现在GRANT里。
CREATE USER 必须显式指定 host 和密码插件
MySQL 8.0 默认使用 caching_sha2_password 插件,但很多老客户端(如某些版本的 Navicat、DBeaver、PHP mysqli 扩展)不兼容,连接时会卡在 authentication failed。
- 创建用户时若不指定插件,
CREATE USER 'u'@'%' IDENTIFIED BY 'pwd'会默认用caching_sha2_password。 - 兼容性写法(推荐):
CREATE USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd'; -
host必须精确匹配,'u'@'localhost'和'u'@'%'是两个完全不同的用户,不能互相替代权限。
授权后要不要执行 FLUSH PRIVILEGES
大多数情况下不需要。MySQL 8.0 的权限系统是动态加载的,CREATE USER 和 GRANT 语句本身就会立即生效。
- 仅在直接修改
mysql.user表(不推荐)后才需FLUSH PRIVILEGES。 - 执行了
FLUSH PRIVILEGES不会出错,但属于冗余操作,还可能掩盖权限未生效的真实原因(比如host写错、用户不存在、或客户端缓存了旧连接)。 - 验证是否成功:用
SHOW GRANTS FOR 'u'@'%';查看,而不是靠重连测试。
远程访问失败?重点检查三处
即使用户创建和授权都正确,远程仍连不上,大概率不是权限问题,而是网络或认证配置没对齐:
- 确认 MySQL 服务监听的是
0.0.0.0(而非仅127.0.0.1),检查bind-address配置项; - 确认防火墙放行了 3306 端口(Linux
iptables/ufw,Windows 防火墙); - 确认客户端连接字符串里的 host、port、user、password 全部匹配,且驱动支持
caching_sha2_password—— 不确定就建用户时强制指定mysql_native_password。
真正容易被忽略的点是:MySQL 8.0 把「谁可以创建用户」和「谁可以授予权限」拆成了两个独立权限(CREATE USER 权限 vs GRANT OPTION),而默认 root 账户虽有全部权限,但这个分离设计让 DBA 必须明确每一步意图——少一个 CREATE USER,后面所有 GRANT 都会失败。


















