MySQL 8.0 中 GRANT 语句不支持 IDENTIFIED BY,必须拆分为 CREATE USER(显式指定认证插件)和 GRANT 两步执行,否则报 ERROR 1064;用户已存在时应改用 ALTER USER,且需验证插件、角色默认激活及 host 精确匹配。
MySQL 8.0 在语法解析阶段就拒绝 GRANT ... IDENTIFIED BY 这种写法,不是权限不够或密码错,而是 parser 根本不认这个结构。你看到的 ERROR 1064 (42000) 就是它——连执行都没走到,更别说建用户了。
常见问题表现:
GRANT SELECT ON mydb.* TO 'u'@'%' IDENTIFIED BY 'p'; → 立刻报错CREATE USER 负责身份认证:用户名、host、密码、认证插件(比如 caching_sha2_password 或 mysql_native_password)、密码过期策略;GRANT 只管权限分配,不碰密码、不改插件、不设生命周期。
所以必须分两步:
CREATE USER 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'p';GRANT SELECT ON mydb.* TO 'u'@'%';漏掉 IDENTIFIED WITH 就会默认用 caching_sha2_password,老客户端(如某些版本 Navicat、PHP mysqli)连不上,只报 Access denied,根本不会提示插件不匹配。
如果 CREATE USER 'u'@'%' 报 ERROR 1396 (HY000),说明用户已存在。这时候该用 ALTER USER 改密码,而不是重复执行 CREATE USER。
实操建议:
IF NOT EXISTS: CREATE USER IF NOT EXISTS 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'p';
ALTER USER 'u'@'%' IDENTIFIED BY 'new_p';,注意这会把认证插件悄悄重置为默认值GRANT 后不执行 FLUSH PRIVILEGES 也能生效,但涉及角色默认激活时,SET DEFAULT ROLE 必须显式执行,否则 SHOW GRANTS 看得到绑定,实际查询仍 Access denied
5.7 脚本能跑,8.0 直接挂,不是因为语法“升级”,而是设计逻辑变了。兼容写法必须避开所有隐式行为:
GRANT ... IDENTIFIED BY,拆成 CREATE USER + GRANT
CREATE USER 必须显式指定插件,推荐 IDENTIFIED WITH mysql_native_password BY,避免客户端兼容问题GRANT ALL PRIVILEGES ON *.* 自动覆盖库级操作——它不等于 GRANT CREATE ON db.*,建表失败往往就卡在这里真正容易被忽略的,不是怎么写对,而是改完之后没验证认证插件是否真生效、没确认角色是否设了默认激活、也没检查 host 是否精确匹配('u'@'localhost' 和 'u'@'127.0.0.1' 是两个用户)。