mysql 8.0 彻底移除 grant 中 identified by 语法,必须拆分为 create user + grant 两步,且需显式指定认证插件(如 mysql_native_password),否则即使语法正确也会因插件不兼容导致连接失败。

MySQL 8.0 中所有含 IDENTIFIED BY 的 GRANT 语句都会直接报 ERROR 1064 或 ERROR 1410,这不是拼写或权限问题,是语法被解析器硬性拒绝——必须拆成 CREATE USER + GRANT 两步,且认证插件不显式指定,后续连接大概率失败。
GRANT 报 ERROR 1064 / 1410 怎么快速确认是版本问题
别猜,先查真实版本:
SELECT VERSION();
如果返回 8.0.33、8.3.0 或类似格式,就坐实了。错误一定出在 GRANT 语句里写了 IDENTIFIED BY ——哪怕只多一个空格,解析器也拒绝执行。常见错误写法包括:
GRANT SELECT ON mydb.* TO 'u1'@'%' IDENTIFIED BY 'pwd123';GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' IDENTIFIED BY 'p';
这些在 5.7 能跑通,在 8.0 必炸,且错误位置总卡在 IDENTIFIED 关键字附近。
CREATE USER 和 GRANT 必须严格分步且顺序不能反
MySQL 8.0 把“建用户”“设密码”“授权限”三件事完全解耦,任何混用都会失败:
- 先执行
CREATE USER:必须带完整'user'@'host',且推荐显式指定插件(见下节) - 再执行
GRANT:只写权限,不带密码、不带插件、不带IDENTIFIED BY - 最后可选
FLUSH PRIVILEGES:脚本批量操作后建议加,避免权限延迟生效
顺序颠倒会报 ERROR 1396 (HY000):“Operation CREATE USER failed”,因为 GRANT 找不到对应用户;重复执行 CREATE USER 也会报同错,此时应改用 ALTER USER 更新密码。
认证插件不指定,语法对也连不上
即使 CREATE USER 和 GRANT 全对、FLUSH PRIVILEGES 也执行了,客户端仍可能卡在 “Authenticating…” 或报 Access denied ——这是 caching_sha2_password 插件不兼容导致的握手失败,不是权限问题。
解决方法只有一条:创建时就锁定插件:
- 正确写法:
CREATE USER 'u1'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123'; - 错误写法:
CREATE USER 'u1'@'%' IDENTIFIED BY 'pwd123';(默认插件,大概率连不上) - 已有用户更新:
ALTER USER 'u1'@'%' IDENTIFIED WITH mysql_native_password BY 'newpwd';
注意:IDENTIFIED WITH 和 BY 必须成对出现,漏掉 BY 会触发密码强度校验或语法错误。
跨版本初始化脚本怎么写才安全
如果你的部署脚本要同时支持 5.7 和 8.0,别靠 SET sql_mode 或人工判断版本,用 MySQL 原生条件注释:
- 用户创建用:
/*!50700 CREATE USER IF NOT EXISTS 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'p' */;(5.7+ 执行,旧版跳过) - 权限授予用普通
GRANT:GRANT SELECT, INSERT ON mydb.* TO 'u'@'%';(所有版本都认) - 避免
GRANT ALL PRIVILEGES ON *.*:它在 8.0 会隐式包含BACKUP_ADMIN等高危权限,生产环境应按库精确授权
最易被忽略的是:插件兼容性和 SYSTEM_USER 权限问题,它们不会在 SQL 执行时报错,而是在应用第一次 connect() 时静默失败——排查时得从连接日志和 SELECT user, host, plugin FROM mysql.user 查起。











