迁移策略与模式:全量迁移、增量迁移、双写迁移

数据迁移不是简单的「把A搬去B」。选错模式,后面全得重来。我记得刚带团队那会儿,有人拍脑袋选了全量,结果30TB的数据跑了三天三夜,业务方天天催,最后回滚比迁移还痛苦。

你想想看,迁移模式直接决定你的停机窗口、数据一致性和回滚复杂度。我个人习惯把这个章节放在最前面讲——先把策略定了,后面的SDK适配才有方向。

全量迁移——最直接,也最暴力

全量迁移就是把源头数据一股脑全倒过去。听起来简单,实操里到处都是坑。

什么时候用?数据量小(百GB以内),业务允许长时间停机。比如内部系统升级、老系统下线。

全量迁移的核心流程

  1. 导出全量数据(mysqldump / pg_dump / 快照)
  2. 传输至目标环境
  3. 目标库导入
  4. 校验行数和关键字段
  5. 切换流量

优点很明显:逻辑简单,回滚也简单——保留源库备份就行。但缺点同样致命:停机时间等于数据搬完的时间。我在项目中遇到过一家金融公司,50GB数据用带宽跑了一个半小时,业务中断直接导致KPI崩盘。

我曾经踩过的坑:全量迁移时忘了关外键检查,导入到一半报错,数据没完全落地,源库又没做一致性快照,最后只能重新导出。从那以后我定了个规矩——全量迁移前必须打快照,并且开一个事务级别的导出。

增量迁移——细水长流,但别松了那根弦

增量迁移只搬变化的数据。说白了,就是先做一次全量基线,然后持续同步增量。我偏爱这个模式,因为它可以做到近乎零停机。

增量数据怎么抓?三种主流玩法:

  • 时间戳/版本号:最常用,比如 updated_at 字段。注意时区和精度问题。
  • CDC日志(Change Data Capture):解析 binlog、redo log。准实时,但不支持所有数据库。
  • 触发器:建个变更表记录增删改。简单但影响源库性能,我一般不推荐。

我的经验:用时间戳做增量时,一定要处理“时间回拨”和“精度丢失”。有一次业务端双写时改了系统时间,导致一批数据没被扫到,丢单了。后来我统一用协调时钟 + 微秒级时间戳才搞定。

增量迁移最难的地方在于一致性校验。源和目标一直在变,你怎么证明两边数据最终一致?我个人习惯在增量同步结束后,做一轮全量比对,如果差异超过阈值就重跑。

双写迁移——最稳妥,也最复杂

双写迁移不是「先写A再写B」,而是同时写入旧系统和新系统。你想想看,用户写一条数据,两个地方都落盘。等校验通过后,再切到只写新系统。

我为什么偏爱双写?因为它能提供最强的回滚能力——切过去发现不对,把流量切回旧系统就行,数据不会丢。但代价也最高。

双写迁移的标准步骤

  1. 部署SDK代理层,拦截写入请求,同时转发给旧库和新库
  2. 后台异步比对两边写入结果
  3. 比对一致率超过99.99%后,持续观察一段时间
  4. 切换读流量到新系统
  5. 等待确认正常后,关闭旧库写入

我曾经翻车的一个案例:双写SDK里的重试机制没控制好,新库写入失败后一直重试,导致旧库正常但新库堆积了大量重复数据。回滚时发现新库数据「多」了,比对数小时才排查出来。从此我规定:双写阶段新库写入失败只记录日志,不重试,由事后补偿任务处理。

三种模式对比

维度 全量迁移 增量迁移 双写迁移
停机时间 长(等于迁移耗时) 短(仅切换窗口) 几乎为零
数据一致性 高(单点快照) 中等(需校验) 高(实时比对)
回滚难度 低(保留源库) 中(需恢复增量) 低(切回旧库)
实现复杂度 低 中 高
适用场景 小数据、允许停机 大数据、可接受少量不一致 核心交易、零容忍停机
迁移策略模式对比 全量迁移 导出 → 传输 → 导入 数据快照 停机切换 增量迁移 基线+持续同步 CDC/时间戳 增量校验 双写迁移 双写→比对→切换 SDK代理层 比对&切换 选择策略的核心原则 数据量×停机容忍度÷风险承受能力 = 最优模式

我个人的选择建议:如果让我选,小数据(< 100GB)且能接受停机,用全量,简单暴力;大数据(TB级)且能容忍短暂不一致,用增量;核心支付转账业务,别犹豫,直接上双写,虽然开发量翻倍,但能睡个安稳觉。

三种模式没有的优劣。我见过有人把全量+增量组合成「基線+实时同步」,也见过双写融合了回滚SDK。关键还是那句话——选模式之前,先想好怎么回滚。下一节我们会深入研究每种模式对应的SDK接口设计,但先把策略理清,后面的代码才不会走偏。

嗯,说到代码,其实全量迁移的Python脚本也就几十行,但增量迁移的binlog解析库选型能扯半天。这部分内容我们放到SDK适配的章节详细展开。