逻辑备份是唯一能跨版本、跨环境、带结构还原的迁移路径,但直接用 mysqldump 一把梭容易在大库或高写入场景下失败,因其默认参数不兼容云环境严格模式、字符集隐式转换、GTID冲突、无断点续传机制及缺乏目标端预处理,必须显式配置 --set-gtid-purged=OFF、--skip-triggers、--default-character-set=utf8mb4、--single-transaction 等硬性参数,并提前在目标库设置 sql_mode、字符集、max_allowed_packet 和关闭 binlog 才能稳定迁移。

逻辑备份是唯一能跨版本、跨环境、带结构还原的迁移路径,但直接用 mysqldump 一把梭容易在大库或高写入场景下失败。
为什么不能直接 mysqldump | mysql 管道迁移
看似最简的命令 mysqldump -u root -p mydb | mysql -h cloud-host -u root -p mydb 在真实迁移中常卡在三处:
- 源库和目标库字符集不一致时,
mysqldump默认不显式声明SET NAMES,导致中文乱码或导入中断 - 目标云实例默认开启
sql_mode=STRICT_TRANS_TABLES,而自建库可能宽松;INSERT中 NULL 值或隐式类型转换会直接报错退出 - 管道传输无中间文件,一旦网络抖动或目标端拒绝连接,整个过程就断了,无法续传或定位失败点
必须加的 mysqldump 参数组合
不是“可选”,而是避免恢复失败的硬性要求:
-
--set-gtid-purged=OFF:私有云 MySQL 实例通常未启用 GTID,或 GTID mode 不一致,否则导入时报ERROR 1840 -
--skip-triggers --skip-routines --skip-events:除非你确认所有存储过程、触发器、事件都兼容云环境(比如权限模型、时区、函数支持),否则先跳过——这些对象逻辑备份本身就不含权限定义 -
--default-character-set=utf8mb4+--skip-extended-insert:前者强制统一编码,后者把每条INSERT拆成单行,方便排查某条记录失败,也利于云数据库限流策略下的稳定导入 -
--single-transaction:仅对 InnoDB 表生效,保证备份时刻一致性;若库中混有 MyISAM 表,需提前停写或接受其快照不一致
导入前必须在目标云实例上预处理
云环境的 MySQL 配置往往比自建更严格,不预设就导入必报错:
- 执行
SET SESSION sql_mode='';或按需设为NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES以外的宽松模式(注意:生产环境后续要调回) - 手动创建目标库并指定
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,别依赖 dump 文件里的CREATE DATABASE—— 云平台可能禁用该语句或强制指定参数 - 检查目标库
max_allowed_packet是否 ≥ 源库;dump 文件里单条超长INSERT(尤其含 BLOB 字段)会触发Packets larger than max_allowed_packet - 关闭目标库 binlog 写入:
SET SQL_LOG_BIN = 0;,否则海量INSERT会撑爆云磁盘配额,且没必要记录迁移过程的 binlog
大库迁移时如何分表+断点续传
单库 >5GB 或单表 >1000 万行时,不要全库 dump。拆解是唯一可行路径:
- 用
mysqldump -u root -p mydb table1 table2 ...分批导出核心业务表,非核心日志表用--ignore-table=mydb.log_table跳过 - 每个表 dump 后立即压缩:
mysqldump -u root -p mydb tb1 | gzip > tb1.sql.gz,节省传输时间和云存储空间 - 导入时用
zcat tb1.sql.gz | mysql -u root -p -D mydb,失败后只需重试该表,不影响其他表进度 - 记录已成功导入的表名到文本文件,下次迁移前先
grep -vFf imported_tables.txt all_tables.txt过滤剩余表
真正难的不是命令怎么写,而是判断哪些表能并行导、哪些字段类型在云环境不被支持(比如 TINYINT(1) 被当布尔解析)、以及如何让应用在切换瞬间不感知主键冲突或自增偏移——这些细节没落在 dump 参数里,得靠迁移前 schema 对比和少量数据抽样验证。


















