数据迁移的三种场景

换数据库、换机房、升级大版本、拆分大表,这些动作都要把数据从一个库搬到另一个库。数据迁移按停机时间分为三类:可以停机的离线迁移、必须无感的在线迁移、以及边迁移边验证的滚动迁移。选哪种取决于业务容忍度,交易系统通常不能长时间停机,就只能做在线迁移。

本文核心知识点
  • 全量迁移把存量数据整体搬过去。
  • 增量同步用 binlog 追平迁移期间的新数据。
  • 一致性校验对比新旧库保证没丢没错。
  • 回滚出问题能退回去。
数据迁移配图:蓝色渐变背景左侧老旧灰色数据库圆柱与右侧崭新蓝色数据库圆柱由半透明管道相连,管道内彩色圆点流动,管上方反向箭头,扁平科技插画
数据从旧库流向新库,迁移与同步正是这幅图的意象。

迁移方案设计:停机与在线

离线迁移最简单:停写、导出、导入、切流量,缺点是业务要停。在线迁移的思路是:先全量迁移存量,再用增量同步追平迁移期间的新写入,追平后短暂停写完成切换。方案设计阶段要明确迁移范围、数据量、停机预算、校验方式与回滚条件,这些写进方案文档比直接动手重要。

迁移步骤(在线):
1. 全量导出存量数据
2. 目标库导入并建索引
3. 开启增量同步追平新数据
4. 一致性校验
5. 停写切换流量
6. 观察并择机回滚

迁移窗口尽量选业务低峰,切换时预留回滚能力,宁可切慢一点也不要一锤子买卖。

全量迁移:导出与导入

全量迁移的工具各数据库都有:MySQL 用 mysqldump,PostgreSQL 用 pg_dump。导出时注意一致性快照:加事务一致性选项,保证导出的是同一时间点的数据,避免导出过程中数据还在变。导入前先在目标库建好表结构与索引,导入后再补索引往往比先建索引快。

mysqldump --single-transaction --source-data=2 \
  mydb > dump.sql
mysql target < dump.sql

数据量大时用流式导出导入,避免一次性读进内存;表结构改动要提前评估,导入脚本要可重复执行,幂等防重。

增量同步:binlog 与 Canal

全量迁移后,迁移期间新产生的数据要靠增量同步追平。MySQL 的 binlog 记录了所有写操作,订阅 binlog 重放到目标库就能保持两边一致。Canal 是常用的 binlog 订阅工具,伪装成从库读取 binlog,把变更解析成结构化事件。

# Canal 配置示意
canal.instance.master.address = old-db:3306
canal.instance.dbUsername = canal
canal.instance.filter.regex = mydb\..*

增量同步要注意主键与唯一键冲突,两边库结构不同时要写映射转换;同步程序要带位点记录,重启后能从上次位置继续,不丢不重。