MySQL 8.0 彻底移除 GRANT 中 IDENTIFIED BY 语法,用户创建(CREATE USER)、授权(GRANT)和密码修改(ALTER USER)必须分离,且须显式指定认证插件如 mysql_native_password。

GRANT 语句里写 IDENTIFIED BY 直接报错 ERROR 1064
这不是语法写错了,是 MySQL 8.0 彻底删掉了这个能力。你执行 GRANT ALL ON *.* TO 'u'@'%' IDENTIFIED BY 'p',解析器在 IDENTIFIED BY 处就停住,抛出 ERROR 1064 (42000) —— 因为该关键字在 GRANT 的语法树中已不存在。
背后是权限模型的重构:用户身份(who)和权限策略(what they can do)被强制解耦。CREATE USER 负责注册身份+认证方式,GRANT 只管授权动作,ALTER USER 才负责改密或换插件。
- 旧版 MySQL 5.7 允许一步完成建户、设密、赋权;8.0 把这三件事拆成三个独立命令,不可合并
- 试图复用老脚本或自动化工具时,只要 GRANT 后面带
IDENTIFIED BY,必挂 - 错误提示不会告诉你“这是被移除了”,只会说“syntax error near ...”,容易误判为拼写问题
CREATE USER 不指定认证插件,连都连不上
即使 CREATE USER 和 GRANT 分开了,也常卡在连接阶段:客户端报 ERROR 1251 或直接断开,但 SQL 执行本身是成功的。
原因是 MySQL 8.0 默认用 caching_sha2_password 插件,而很多老客户端(如 Navicat 11、旧版 JDBC 驱动、PHP mysqli)不支持它。
- 必须显式写
IDENTIFIED WITH mysql_native_password BY 'p',不能只写IDENTIFIED BY 'p' -
IDENTIFIED BY是隐式调用默认插件,IDENTIFIED WITH ... BY才是显式指定,二者不能混用 - 如果已创建用户但插件不对,得用
ALTER USER 'u'@'h' IDENTIFIED WITH mysql_native_password BY 'p'改,再FLUSH PRIVILEGES
ALTER USER 是唯一合规的密码修改入口
MySQL 8.0 彻底移除了 PASSWORD() 函数,UPDATE mysql.user SET authentication_string = ... 这类操作不仅过时,还极可能让账户无法登录——因为没触发认证插件的内部校验逻辑。
所有密码变更必须走 ALTER USER,哪怕只是重置 root 密码也一样。
- 正常场景:
ALTER USER 'u'@'h' IDENTIFIED BY 'newpass' - 兼容旧客户端:
ALTER USER 'u'@'h' IDENTIFIED WITH mysql_native_password BY 'newpass' - 忘记原密码?只能进
--skip-grant-tables模式,但注意:8.0 中必须加--console --shared-memory参数才生效,且改完必须用ALTER USER设置密码,不能直接 UPDATE 字段
REVOKE 权限时突然报 SYSTEM_USER 权限不足
当你对一个拥有 SYSTEM_USER 权限的账号执行 REVOKE ALL ON *.* FROM 'u'@'%',会收到 ERROR 1227 (42000),提示缺 SYSTEM_USER 权限。
这不是 bug,是 8.0.16+ 新增的权限控制粒度:用户管理本身也被纳入权限体系。要撤销 SYSTEM_USER 级别的权限,操作者自己也得有该权限。
- 常见于 root 用户或高权限运维账号被误授了
SYSTEM_USER - 普通应用账号一般不需要这个权限,授权时应严格按最小权限原则,避免后续 REVOKE 失败
- 排查时容易忽略这点,以为是语法或网络问题,实际是权限链上缺了一环
复杂点在于:这些限制不是孤立存在的。比如你用 CREATE USER 创建了用户却忘了指定插件,后面用 ALTER USER 改密码时,如果客户端不支持新插件,照样连不上——问题会跨步骤传导,且错误现象和根本原因不在同一层。


















