直接导出 mysql.user 表无法安全还原用户账号,因 caching_sha2_password 的 authentication_string 依赖版本与配置,易致认证失败;须用 mysqldump --no-data 导出 create user/grant 语句,并显式指定插件与哈希。

直接导出 mysql.user 表无法安全还原用户账号
MySQL 8.0+ 默认使用 caching_sha2_password 插件,其密码哈希值存储在 authentication_string 字段中,但该字段内容**依赖 MySQL 版本、插件实现和服务器配置**。直接用 SELECT * FROM mysql.user 导出再导入到另一实例,大概率导致用户无法登录——不是密码错误,而是认证插件不匹配或哈希解析失败。
正确做法:用 mysqldump + --skip-extended-insert 导出用户定义语句
必须绕过直接操作 mysql.user 表,改用 MySQL 原生的账号重建逻辑。核心是让 mysqldump 输出 CREATE USER 和 GRANT 语句,而非表数据:
- 运行:
mysqldump -u root -p --no-data --skip-triggers --compact mysql user db event proc func - 加上
--skip-extended-insert可确保每条INSERT INTO mysql.user被转为带完整列名的单行语句(便于人工检查plugin和authentication_string) - 但更推荐加
--skip-comments和--skip-extended-insert后,用脚本把INSERT行替换成等效的CREATE USER ... IDENTIFIED WITH ... AS 'xxx'(需按目标版本调整插件名) - MySQL 5.7 升 8.0 时,
mysql_native_password用户可保留;若原为sha256_password,8.0 下需显式指定插件才能复用原哈希
升级前必须手动验证每个用户的 plugin 和 authentication_string
不同版本对同一哈希串的解释可能不同。执行以下查询确认关键字段:
SELECT User, Host, plugin, authentication_string, password_expired FROM mysql.user WHERE account_locked = 'N';
-
plugin = 'caching_sha2_password'且authentication_string以$A$开头 → 属于 MySQL 8.0 原生哈希,不能直接用于 5.7 -
plugin = 'mysql_native_password'且authentication_string长度为 41 → 是老式十六进制哈希,兼容性最好 - 若升级目标是 8.0,建议提前运行
ALTER USER 'u'@'h' IDENTIFIED WITH caching_sha2_password BY 'pwd';统一插件,避免混合状态
还原时禁止直接 INSERT INTO mysql.user
MySQL 不允许直接写入 mysql 系统库表(尤其 8.0+ 默认启用 sql_mode=STRICT_TRANS_TABLES),强行导入会报错:ERROR 1356 (HY000): View 'mysql.user' references invalid table(s) or column(s)。正确流程是:
- 先用
CREATE USER建号(含IDENTIFIED WITH ... AS 'xxx'显式指定哈希) - 再用
GRANT恢复权限(注意GRANT不覆盖密码,只补权限) - 对已存在用户,用
SET PASSWORD FOR 'u'@'h' = 'xxx'(5.7)或ALTER USER ... IDENTIFIED WITH ... AS 'xxx'(8.0)更新哈希 - 务必在
FLUSH PRIVILEGES;前确认所有语句语法通过,否则权限加载失败
最易被忽略的是:authentication_string 中的单引号、反斜杠未转义,会导致 SQL 语法错误;导出时没加 --skip-extended-insert,合并的多值 INSERT 在还原时无法定位具体哪一行出错。











