旧用户权限不能直接迁移,因mysql 5.7与8.0的mysql.user表结构不兼容:5.7用password字段和mysql_native_password插件,8.0改用authentication_string字段和caching_sha2_password插件,直接导入会导致字段错位、类型不匹配、校验失败,典型错误包括error 1524和unknown column 'password'。

不能直接导入 mysql.user 表,也不能靠 mysqldump --all-databases 一锅端——8.0 的权限系统结构已彻底重构,硬导会导致连不上、权限丢失、甚至 mysqld 启动失败。
为什么旧用户权限不能直接迁移
MySQL 5.7 的 mysql.user 表含 password 字段、plugin 类型为 ENUM、默认用 mysql_native_password;而 8.0 中字段名改为 authentication_string,plugin 改为 VARCHAR,且默认认证插件是 caching_sha2_password。直接导入会触发字段错位、类型不匹配、校验失败三重报错,典型错误包括:ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded 或 Unknown column 'password' in 'field list'。
- mysqldump 导出的
INSERT INTO mysql.user语句在 8.0 下语法非法 - 即使跳过错误强行导入,
FLUSH PRIVILEGES也无法激活旧用户 - 宝塔或一键脚本若自动执行全库导入,大概率卡在第 12 张表(即
mysql.user)
必须用 CREATE USER + GRANT 重建权限
唯一可靠路径是提取 5.7 用户定义逻辑,手工生成 8.0 兼容的建户语句。不要试图还原旧密码哈希值——8.0 不再支持旧格式解析,且安全策略已收紧。
- 先从 5.7 导出用户清单:
SELECT CONCAT('CREATE USER ''',user,'''@''',host,''' IDENTIFIED BY ''',SUBSTRING_INDEX(authentication_string,'*',-1),''';') FROM mysql.user WHERE user != 'root' AND authentication_string != '';(注意:仅适用于明文密码已知或可重置场景) - 更稳妥做法是统一重置密码:
SELECT CONCAT('ALTER USER ''',user,'''@''',host,''' IDENTIFIED WITH mysql_native_password BY ''newpass123'';') FROM mysql.user WHERE user != 'root'; - 再导出权限:
SELECT CONCAT('GRANT ',privilege,' ON ',db,'.',table_name,' TO ''',user,'''@''',host,''';') FROM information_schema.role_table_grants WHERE user != 'root';(需配合information_schema.role_routine_grants等补全) - 所有语句导出后,在 8.0 实例中执行前,务必先
CREATE DATABASE IF NOT EXISTS mysql;并确认该库是全新初始化的(非从 5.7 恢复)
认证插件与客户端连接必须对齐
即便用户重建成功,老应用仍可能报 Client does not support authentication protocol——这不是权限问题,而是握手协议不匹配。
- 若坚持用
caching_sha2_password(推荐用于新项目),JDBC 连接串必须加:?serverTimezone=UTC&allowPublicKeyRetrieval=true,且驱动版本 ≥mysql-connector-java-8.0.13 - 若要兼容 PHP 5.x / PyMySQL my.cnf 中显式设:
default_authentication_plugin=mysql_native_password - 执行
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpwd';后,立刻FLUSH PRIVILEGES;,否则修改不生效 - 检查是否生效:
SELECT user, host, plugin FROM mysql.user WHERE user = 'root';,结果中plugin列必须是mysql_native_password
最容易被忽略的权限残留点
升级后看似能连、能查,但某些操作仍失败,往往是因为旧版权限模型遗留的“隐形绑定”没清理干净。
-
mysql.db、mysql.tables_priv等表中的 host 字段若含通配符(如%或192.168.%),8.0 会严格校验 DNS 反查,建议改用 IP 段或关闭 skip-name-resolve - 5.7 中通过
GRANT PROXY ON 'a'@'%' TO 'b'@'%'建立的代理关系,在 8.0 中需显式启用:SET PERSIST proxy_user = 'a@%'; - 若业务依赖
DEFINER存储过程或视图,检查其定义者是否存在且 plugin 匹配,否则调用时报Access denied; you need (at least one of) the SUPER privilege(s) - 最隐蔽的是 SELinux 上下文:CentOS/RHEL 上若迁移后
mysqld启动失败且日志无明确报错,运行chcon -R --reference=/var/lib/mysql /var/lib/mysql再试
权限迁移不是 dump 和 restore 就能闭环的事,它本质是两套权限模型之间的映射与重写。哪怕只有一条 CREATE USER 没执行,第二天监控就可能报警连接数耗尽——因为 root 登录失败后,应用不断重试,却始终卡在认证层。











