MySQL迁移需先确认源库与目标库版本兼容性,检查JSON支持、认证插件等差异;导出时禁用autocommit、使用--single-transaction和utf8mb4字符集;目标库须预建用户权限、匹配sql_mode与时区设置;还原前预建库,强制执行并日志分析,最后校验表结构与行数。

确认源库与目标库的 MySQL 版本兼容性
MySQL 迁移失败多数源于版本越级或不兼容特性,比如 JSON 字段在 5.7+ 才原生支持,而 5.6 用 TEXT 模拟会导致 mysqldump 导出后无法导入;又如 8.0 默认认证插件改为 caching_sha2_password,老客户端直连会报 Client does not support authentication protocol。
- 用
SELECT VERSION();分别查源库和目标库版本 - 查官方文档的 Upgrading MySQL 章节,确认是否支持「直接升级」(如 5.7 → 8.0 允许,但 5.6 → 8.0 不推荐)
- 若目标为 8.0,提前在目标库执行
ALTER USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';避免连接中断
导出前必须关闭 autocommit 并设置合理参数
默认 mysqldump 在大表场景下容易因超时、锁表或内存溢出失败。关键不是“能不能导”,而是“导出来的能不能安全还原”。
- 加
--single-transaction(仅对 InnoDB 有效),避免全库锁表;但注意它不能防止 DDL 变更,迁移窗口内禁止执行ALTER TABLE - 禁用
--lock-tables(默认开启),否则 MyISAM 表会锁死整个库 - 显式指定字符集:
--default-character-set=utf8mb4,否则可能因服务端默认latin1导致中文乱码 - 大库建议加
--skip-triggers --skip-routines --skip-events,这些对象单独导出更可控
mysqldump -h source_host -u user -p --single-transaction --default-character-set=utf8mb4 --routines --triggers --databases db1 db2 > backup.sql
目标库需预建用户、权限及基础配置
很多迁移卡在还原阶段,不是 SQL 有问题,而是目标库缺少对应用户或权限不足,例如 CREATE PROCEDURE 需要 CREATE ROUTINE 权限,而 GRANT ALL PRIVILEGES 并不自动包含它。
- 用
SHOW CREATE USER 'user'@'%';查源库用户定义,注意REQUIRE SSL或密码过期策略是否需同步 - 目标库执行
CREATE USER后,必须显式GRANT所需权限,不要依赖GRANT ALL - 检查
max_allowed_packet:若导出文件含大 BLOB,目标库该值需 ≥ 源库,否则ERROR 2006 (HY000): MySQL server has gone away - 确认
sql_mode一致,尤其避免目标库开了STRICT_TRANS_TABLES而源库没开,导致插入空字符串失败
验证迁移脚本能否在目标环境干净执行
直接 mysql 是最危险的操作——一旦中途报错,库可能处于半还原状态,且无回滚机制。
- 先用
mysql -h target -u user -p -e "CREATE DATABASE IF NOT EXISTS db1 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;"预建库 - 用
mysql --verbose --force restore.log强制继续并记录全部输出 - 重点 grep 日志:
grep -E "(ERROR|Warning)" restore.log,常见有Unknown table 'xxx'(触发器引用了不存在的表)、Cannot add or update a child row(外键顺序错) - 还原后立即执行
CHECK TABLE和SELECT COUNT(*)对比行数,不要只信 “Query OK”
最容易被忽略的是时区和 lower_case_table_names 设置:若源库在 Linux(区分大小写)而目标在 Windows(不区分),mytable 和 MyTable 会被视为同一张表,导致覆盖或丢失。










