Skip to content

10 · 数据迁移与双写 ​

换库/加字段/分表最怕的不是迁移本身,而是迁移后才发现两边对不上。本篇讲平滑迁移的套路:评估、全量+增量、双写、校验、切换与回滚,让"上线"变成"可验证、可回退"。

速览卡 ​

项内容
一句话定位数据库迁移的操作指南:从评估到切换,每一步都有校验与回滚
核心内容全量/增量/双写/校验/灰度切换/回滚,一套可复用的迁移流程
读完能回答迁移期间新旧库不一致怎么办?怎么证明迁移成功?
相关板块DB03 事务 | DB08 分库分表 | C04 一致性与事务

一、迁移前的三件事 ​

事项内容
评估数据量、字段映射、停机窗口、回滚方案
迁移脚本可重放幂等:重复跑结果一致
先定验收标准"什么算成功"要预先定义,不是上线后拍脑袋

验收标准示例:抽样 N 条对比一致率 100%、特定边界字段正确、双写期间新增数据无丢失。


二、平滑迁移的六步流程 ​

text
① 全量迁移   历史数据一次性搬过去
② 增量同步   迁移期间的新写入实时同步
③ 双写       新旧两套都写,校验后以新为准
④ 校验       对比两边数据,修差异
⑤ 灰度切换   逐步把读/写切到新库
⑥ 观察 + 回滚窗口   出问题立即回退

三、全量迁移:先搬家 ​

sql
-- 迁移方向:旧表 → 新表(可写一段脚本做字段映射/清洗)
INSERT INTO new_table (id, name, created_at)
SELECT id, name, created_at FROM old_table;

要点:

  • 大表分批插入(LIMIT + 游标),避免一次锁太久
  • 跑之前先停写或接受"迁移期间增量差异"
  • 迁移完成立刻对比数量(行数、校验和)

四、增量同步:让差异可控 ​

全量搬完的那一刻,新库就落后了——期间的写入需要增量补。

方案机制
binlog 订阅监听旧库变更,同步到新库(最通用)
时间戳增量按 updated_at > 上次位置 轮询拉取
应用双写写旧库同时写新库(见下)

五、双写:新旧都写,校验为准 ​

text
写请求 → 写旧库 + 写新库
         ↓
         (新库写失败?记日志,不阻塞主流程)
读请求 → 仍读旧库,直到切换
好处代价
新库数据持续最新双写失败要补偿
切换前就有真实数据应用代码要改两处

判断框架:迁移窗口内写流量大 → 双写让新库"热身";写流量小 → 先全量再增量,可能不需要双写。


六、校验:证明迁移成功 ​

校验层做法
行数两表 COUNT 一致
抽样按 id 抽样对比关键字段
全量哈希按行算哈希聚合后对比
边界字段时间、金额、NULL、超长字段
业务探针跑几条真实业务查询对比结果

校验不能只对一次:双写期间要周期校验,发现漂移就修复后继续。


七、灰度切换与回滚 ​

步骤动作
读灰度小比例流量读新库,观察错误/延迟
写灰度小比例流量写新库
全量切换确认稳定后全部切走
回滚窗口保留旧库一段时间(按业务定,如 1~2 周),必要时切回

回滚不是"一键搞定":旧库可能没有新写入,要设计"新→旧"的反向同步或接受数据回退。


八、自检清单 ​

  • [ ] 迁移前先定验收标准与回滚方案
  • [ ] 全量迁移分批执行、跑完立刻对比数量
  • [ ] 迁移窗口的增量用 binlog/时间戳/双写补上
  • [ ] 双写期间周期校验,不只看一次
  • [ ] 灰度切换分读/写两阶段
  • [ ] 保留回滚窗口,且有数据回退预案

九、常见误区 ​

误区事实
"迁移一次就完"增量、校验、灰度都要跟上
"两边数量对得上就行"要校验内容与边界字段
"双写失败不影响"要记录补偿,否则新库缺数据
"切换完就能删旧库"保留回滚窗口,出问题能退
"回滚是无损的"新库写入旧库没有时,要接受回退或反向同步
"迁移脚本跑一遍就好"要幂等可重放

十、动手练习 ​

练习 A:写迁移验收标准 ​

给"用户表从 MySQL 迁到 Postgres"写一份验收清单(数量、抽样、边界、业务探针各两条)。

练习 B:设计双写补偿 ​

双写时新库偶发失败,你怎么保证最终一致?画出"失败 → 重试 → 对账"的链路。

练习 C:模拟灰度 ​

流量按 1% → 10% → 50% → 100% 切读,每阶段看什么指标才放行下一阶段?


相关文档 ​

本区 ​

其他域 ​