MySQL 8.0 不支持 CREATE USER ... LIKE 语法,执行必报 ERROR 1064;可靠方式仅有手动三步法(CREATE USER + SHOW GRANTS + GRANT)或 mysqlpump --users 导出可执行语句。

MySQL 8.0 不支持 CREATE USER ... LIKE,所谓“一键克隆”是无效操作,执行必报 ERROR 1064 (42000)。真正可靠的方式只有两种:手动用 SHOW GRANTS + CREATE USER + GRANT,或用 mysqlpump --users 导出可执行语句。
为什么 CREATE USER 'new'@'%' LIKE 'old'@'%' 会失败
这不是配置问题,也不是权限不足,而是该语法在 MySQL 官方任何版本中都不存在。它只存在于 MariaDB 10.2+。你执行时看到的错误是解析器直接拒绝识别该关键字。别查文档了——MySQL 8.0 的 SQL 语法手册里根本没这行字。
-
SHOW GRANTS FOR 'old'@'%'返回的是完整授权语句,但目标用户必须已存在才能执行其中带WITH GRANT OPTION的语句 - 原用户若被授予了角色(
ROLE),SHOW GRANTS FOR 'old'@'%'不会显示角色授权,需额外查mysql.role_edges - 如果原用户 host 是
'%.example.com',而新服务器 DNS 解析行为不同(比如skip_name_resolve=OFF),权限可能不匹配
手动克隆:三步走,每步都得做对
适用于单个用户、跨版本迁移、或需要审查每条权限的场景。关键不是“快”,是“可控”。
- 先创建空用户,显式指定认证插件:
CREATE USER 'newuser'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123';(避免caching_sha2_password导致旧客户端连不上) - 查原用户权限:
SHOW GRANTS FOR 'olduser'@'%';,把每行输出里的'olduser'@'%'替换成'newuser'@'%',注意保留引号和分号 - 若原用户有默认角色:
SELECT FROM_USER, FROM_HOST FROM mysql.role_edges WHERE TO_USER = 'olduser' AND TO_HOST = '%';,对每个结果执行GRANT ROLE 'role_name'@'host' TO 'newuser'@'%';
用 mysqlpump --users 批量导出,但参数不能少
mysqlpump 默认不导出用户,只导权限;不加特定参数,导入时会报 ERROR 1133 (42000): Can't find any matching row in the user table。
- 必须组合使用:
mysqlpump --users --include-databases=mysql --skip-definer --add-drop-user --skip-triggers - 导出后检查 SQL 文件是否含
CREATE USER行(不是只有GRANT);若没有,说明--users没生效或权限不足 - 导入时务必用
root@localhost执行,普通账号即使有GRANT OPTION也缺INSERT权限写mysql.user - 从 8.0 → 5.7 迁移时,导出文件中的
IDENTIFIED WITH caching_sha2_password AS 'xxx'必须手动替换成IDENTIFIED BY PASSWORD 'xxx',否则语法报错
最容易被忽略的三个点
不是忘了 FLUSH PRIVILEGES,而是根本不需要——用 GRANT 或 CREATE USER 语句创建/授权,权限立即生效。真正容易翻车的是:
- 新用户 host 写成
'%',但应用实际连接 IP 被反向 DNS 解析成域名,而权限里没配对应域名 host —— 检查skip_name_resolve设置 - 原用户密码哈希来自
caching_sha2_password,新库虽能导入,但 PHP 7.2、Node.js mysql2 等旧驱动无法完成握手 —— 必须提前降级插件 - 用
mysqldump mysql user直接导入,字段缺失(如 8.0 多了password_reuse_history)、类型不匹配(account_locked是 ENUM 不是 TINYINT),导致整个导入中断


















