mysql 5.7 的 mysql.user 表含 password 字段,8.0 已改为 authentication_string,且默认认证插件升级为 caching_sha2_password,直接导入 --all-databases 会覆盖 8.0 初始化的权限元数据,导致启动失败或用户无法登录;必须剥离系统库、替换密码函数、指定兼容插件重建用户。

mysql.user 表结构已变,直接导入 5.7 的权限数据会导致 8.0 启动失败或用户无法登录。必须剥离系统库、重写认证方式、手动重建权限。
为什么 mysqldump --all-databases 会破坏 8.0 权限系统
5.7 的 mysql.user 表含 password 字段,8.0 已改为 authentication_string;导出文件若包含该表,导入后会覆盖 8.0 初始化的权限元数据,造成 Access denied for user 或服务启动卡在权限加载阶段。
- 绝对不要用
mysqldump --all-databases导出,它会把整个mysql库打包进去 - 即使只导出业务库,也要检查 SQL 文件开头是否有
SET sql_mode = 'NO_AUTO_CREATE_USER'—— 这个模式在 8.0 已被移除,执行即中断 - 5.7 中用
PASSWORD()函数生成的密码哈希值,8.0 不再识别,必须转为caching_sha2_password或降级兼容插件
如何安全导出并重建用户与权限
核心思路:不迁移 mysql 表,只提取“谁对哪些库/表有什么权限”,然后用 8.0 兼容语法重建。
- 在 5.7 上执行:
mysqldump -u root -p --no-create-info --skip-extended-insert --compact mysql user db tables_priv columns_priv procs_priv > grants_57.sql - 用脚本或手动删掉
grants_57.sql中所有INSERT INTO `user`行(保留db、tables_priv等授权表的 INSERT) - 将所有
PASSWORD('xxx')替换为UNHEX('...')或直接改用明文密码 + 指定插件(见下一步) - 导入前,在 8.0 中先创建用户:
CREATE USER 'u1'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd1';(如需兼容老驱动)
认证插件不匹配导致连接失败的处理
8.0 默认用 caching_sha2_password,但 5.7 用户是 mysql_native_password;若客户端驱动旧(如 PyMySQL Authentication plugin 'caching_sha2_password' cannot be loaded。
- 临时方案:在 8.0 启动时加配置
default_authentication_plugin=mysql_native_password,再重建用户 - 长期方案:升级客户端驱动,并为每个用户显式指定插件:
ALTER USER 'u1'@'%' IDENTIFIED WITH caching_sha2_password BY 'pwd1'; - 验证是否生效:
SELECT user, host, plugin FROM mysql.user WHERE user = 'u1';,确保plugin字段值与客户端支持的一致
权限语句导入时报错 ERROR 1410 或 ERROR 1044 怎么办
常见于 GRANT 语句中指定了不存在的数据库、表,或用了 8.0 已弃用的权限关键词(如 FILE、PROCESS 在严格模式下受限)。
- 先在 8.0 中创建对应数据库:
CREATE DATABASE IF NOT EXISTS myapp; - 删掉 GRANT 语句中的
IDENTIFIED BY子句(用户已建好,权限和认证要分开) - 把
GRANT ALL PRIVILEGES ON *.*拆成更细粒度的授权,避免触发super_priv校验失败 - 导入后运行
FLUSH PRIVILEGES;,否则变更不生效
SELECT 权限不再隐式包含 SHOW VIEW,EXECUTE 权限也不再自动赋予存储过程调用权。如果应用依赖这些隐式行为,光靠还原 GRANT 语句是不够的,必须逐条补全。











