Contents

零停机数据库迁移:DTS 与备份导入方案技术选型

数据库迁移看起来像“搬家”,但线上系统的真实难点是:你不能让业务停太久,且不能在切换时把数据写乱。无论是上云、跨地域、引擎升级还是存储替换,本质都绕不开三个问题:

  • 停机窗口:允许停写多久?是秒级、分钟级,还是可以有几个小时维护窗口?
  • 一致性与可回退:切过去后发现问题,能不能快速回切?回切后数据是否还能对齐?
  • 执行成本:团队能否承受更复杂的链路(日志订阅、增量追赶、割接演练、监控告警)?

本文只讨论两条最常见路线:DTS/CDC 在线迁移停机 + 备份导入。目标不是“讲概念”,而是让你能用它做一次迁移。

在线迁移的核心是:先把存量搬过去,再靠 变更日志 把增量追上,最后在一个很短的停写窗口完成切换。

最常见的三段式流程:

  1. 结构迁移:表/索引/视图等 DDL
  2. 全量迁移:把历史数据灌到目标库(通常建议低峰执行)
  3. 增量同步:持续消费变更日志(MySQL Binlog、SQL Server CDC 等),把新写入实时/准实时应用到目标库,直到割接完成

它的价值很直接:

  • 业务中断很小:最终切换通常只需要秒级到分钟级的停写(取决于系统的“停写能力”和验证手段)
  • 更适合大库:数据越大,“一次性备份导入”的风险越高,而增量追赶可以把压力摊平

它也有明确代价:

  • 依赖日志能力:源库必须能稳定产生日志,并允许订阅;日志配置不对会直接导致丢数据/延迟
  • 割接流程更严格:最后一公里全靠流程纪律(停写、追平、校验、切换、观测)

一个最小的“能跑起来”的前置检查清单(以 MySQL 为例):

  • 源库已开启并保留足够的 Binlog,且格式满足迁移工具要求(常见要求是 ROW
  • 迁移账号具备读取数据与订阅日志的权限,目标库具备写入权限
  • 目标库参数、字符集/排序规则、时区等与源库兼容(否则容易出现隐性差异)

这条路的逻辑很朴素:停写 → 备份 → 传输 → 导入 → 验证 → 切连接 → 恢复。

典型流程(也是你该写进变更单的顺序):

  1. 公告维护窗口并冻结变更(代码/DDL/配置)
  2. 应用进入维护模式或直接停写
  3. 备份导出(逻辑或物理)
  4. 传输备份到目标环境
  5. 导入恢复
  6. 验证数据与关键链路
  7. 切换连接并恢复服务

它的优势是可预测:

  • 工具链成熟、理解成本低
  • 强一致:备份点就是一致性边界,不存在“追增量”的问题
  • 回退简单:只要备份后源库确实没有写入,回切就是把连接指回去

它的上限也很明显:中断时间会随数据量线性变长。你可以用一个粗略公式评估维护窗口:

停机时长 ≈ 停写 + 备份 + 传输 + 导入 + 验证

当数据到 TB 量级,任何一个环节超时/失败都很常见,整次迁移会变成一次“赌运气”。

一些更具体的例子(用来估算与演练):

  • MySQL 逻辑备份(常见选项:一致性快照、带上触发器/事件):
mysqldump --single-transaction --routines --triggers --events dbname > db.sql
  • MySQL 并行导出/导入(更适合大库、表多的场景):
mydumper -B dbname -o dump_dir -t 8
myloader -B dbname -d dump_dir -t 8
  • PostgreSQL 并行恢复(配合目录格式):
pg_dump -Fd -j 8 -f dump_dir dbname
pg_restore -j 8 -d dbname dump_dir

先给两个经验判断(不是绝对阈值,最终以你的吞吐与窗口为准):

  • 停机只能秒级/分钟级:优先考虑在线迁移(DTS/CDC)
  • 窗口足够且数据不大:备份导入往往更省心

然后按四个维度做最终判断:

  1. 业务容忍度:停机影响是否可控(收入、用户、SLA、舆情)
  2. 数据规模与写入强度:库大不一定难,难的是“高写入 + 长时间无法停写”
  3. 技术可行性:日志能力、网络带宽、跨云/跨地域链路、版本/引擎差异
  4. 团队执行力:是否能把割接流程演练到“闭眼都能跑”

一个更贴近实战的矩阵:

约束/场景 更推荐 为什么
生产核心链路、需要 7×24 在线迁移(DTS/CDC) 最小化停写窗口
大库或恢复时间不可预测 在线迁移(DTS/CDC) 把压力摊到增量追赶阶段
有明确维护窗口且流程可控 备份导入 简单、强一致、回退直观
测试/预发布/报表库 备份导入 复杂度不值得
源库无法稳定提供日志能力 备份导入 在线迁移不可用或风险过高

在线迁移不是难在“同步”,而是难在“切换”。事故通常来自一个词:冲突(双写、主键冲突、覆盖更新、逻辑状态错乱)。

割接最小闭环(建议当作 Checklist):

  1. 停写(冻结源库写入):维护模式/网关断流/停应用都可以,关键是“确认真的没有写入”
  2. 追平增量:等待/触发同步延迟收敛到可接受范围(最好是 0 或接近 0)
  3. 最终校验:抽样校验不够的话,做校验和或表级对账
  4. 切连接:配置批量切换,保证一次性生效
  5. 恢复写入与观测:确认新流量只写目标库,监控错误率、延迟、关键指标
  6. 保留回退路径:源库先只读保留一段观察期,再决定退役

一致性校验的例子(MySQL):

pt-table-checksum --nocheck-replication-filters --databases=dbname h=src_host

如果你确实在割接前让应用同时写源库与目标库(即“双写”),除非你有明确的冲突解决策略(例如幂等写、业务层去重、统一序列号与严格顺序保证),否则迁移工具一般救不了你。

  • 先预演再上生产:至少跑通一次“全量 + 增量 + 割接 + 回退”的全链路演练
  • 限速与资源隔离:全量阶段要避免压垮源库;目标库要留出足够写入与索引构建能力
  • 监控与告警:同步延迟、失败重试、目标库写入错误、源库日志增长与保留期
  • 迁移对象最小化:先迁必要库/表,减少第一次割接的不确定性
  • 并行化优先:大多数时候瓶颈在导入,优先选择支持并行恢复的工具链
  • 物理备份更稳:超大库更建议快照/物理备份(例如 Xtrabackup),避免逻辑导入“跑到一半失败”
  • 传输别靠运气:专线/对象存储直传/断点续传能力,往往比“scp 一把梭”可靠
  • 拆分策略:按业务域或时间范围分批迁移,减少单次失败的爆炸半径
  • 权限:源库读 + 日志访问;目标库写;提前验证而不是割接时临时加权限
  • 容量与性能:CPU/内存/IOPS/磁盘空间,建议预留余量(例如 30%+),并确保参数与连接数上限匹配
  • 回退:写清楚“什么时候回退、怎么回退、回退要做哪些清理”,并预留执行时间
  • 沟通:迁移窗口、影响范围、冻结策略、负责人与应急联系人
  • 如果你要的是 最小停机 + 可扩展到大库,在线迁移(DTS/CDC)更合适,但成功依赖严格割接流程与可观测性。
  • 如果你有 明确维护窗口 + 数据规模可控,停机备份导入往往更稳、更省心,关键在于并行化与演练。

最终决定不在 PPT 上,而在你能否把“停写、校验、切换、回退”四件事做成一套可重复的流程。