零停机数据库迁移:DTS 与备份导入方案技术选型
Contents
引言:零停机迁移到底难在哪
数据库迁移看起来像“搬家”,但线上系统的真实难点是:你不能让业务停太久,且不能在切换时把数据写乱。无论是上云、跨地域、引擎升级还是存储替换,本质都绕不开三个问题:
- 停机窗口:允许停写多久?是秒级、分钟级,还是可以有几个小时维护窗口?
- 一致性与可回退:切过去后发现问题,能不能快速回切?回切后数据是否还能对齐?
- 执行成本:团队能否承受更复杂的链路(日志订阅、增量追赶、割接演练、监控告警)?
本文只讨论两条最常见路线:DTS/CDC 在线迁移 与 停机 + 备份导入。目标不是“讲概念”,而是让你能用它做一次迁移。
两种核心方案:原理、流程与适用边界
方案 A:DTS(或 CDC)在线迁移
在线迁移的核心是:先把存量搬过去,再靠 变更日志 把增量追上,最后在一个很短的停写窗口完成切换。
最常见的三段式流程:
- 结构迁移:表/索引/视图等 DDL
- 全量迁移:把历史数据灌到目标库(通常建议低峰执行)
- 增量同步:持续消费变更日志(MySQL Binlog、SQL Server CDC 等),把新写入实时/准实时应用到目标库,直到割接完成
它的价值很直接:
- 业务中断很小:最终切换通常只需要秒级到分钟级的停写(取决于系统的“停写能力”和验证手段)
- 更适合大库:数据越大,“一次性备份导入”的风险越高,而增量追赶可以把压力摊平
它也有明确代价:
- 依赖日志能力:源库必须能稳定产生日志,并允许订阅;日志配置不对会直接导致丢数据/延迟
- 割接流程更严格:最后一公里全靠流程纪律(停写、追平、校验、切换、观测)
一个最小的“能跑起来”的前置检查清单(以 MySQL 为例):
- 源库已开启并保留足够的 Binlog,且格式满足迁移工具要求(常见要求是
ROW) - 迁移账号具备读取数据与订阅日志的权限,目标库具备写入权限
- 目标库参数、字符集/排序规则、时区等与源库兼容(否则容易出现隐性差异)
方案 B:停机 + 备份导入
这条路的逻辑很朴素:停写 → 备份 → 传输 → 导入 → 验证 → 切连接 → 恢复。
典型流程(也是你该写进变更单的顺序):
- 公告维护窗口并冻结变更(代码/DDL/配置)
- 应用进入维护模式或直接停写
- 备份导出(逻辑或物理)
- 传输备份到目标环境
- 导入恢复
- 验证数据与关键链路
- 切换连接并恢复服务
它的优势是可预测:
- 工具链成熟、理解成本低
- 强一致:备份点就是一致性边界,不存在“追增量”的问题
- 回退简单:只要备份后源库确实没有写入,回切就是把连接指回去
它的上限也很明显:中断时间会随数据量线性变长。你可以用一个粗略公式评估维护窗口:
停机时长 ≈ 停写 + 备份 + 传输 + 导入 + 验证
当数据到 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)
- 窗口足够且数据不大:备份导入往往更省心
然后按四个维度做最终判断:
- 业务容忍度:停机影响是否可控(收入、用户、SLA、舆情)
- 数据规模与写入强度:库大不一定难,难的是“高写入 + 长时间无法停写”
- 技术可行性:日志能力、网络带宽、跨云/跨地域链路、版本/引擎差异
- 团队执行力:是否能把割接流程演练到“闭眼都能跑”
一个更贴近实战的矩阵:
| 约束/场景 | 更推荐 | 为什么 |
|---|---|---|
| 生产核心链路、需要 7×24 | 在线迁移(DTS/CDC) | 最小化停写窗口 |
| 大库或恢复时间不可预测 | 在线迁移(DTS/CDC) | 把压力摊到增量追赶阶段 |
| 有明确维护窗口且流程可控 | 备份导入 | 简单、强一致、回退直观 |
| 测试/预发布/报表库 | 备份导入 | 复杂度不值得 |
| 源库无法稳定提供日志能力 | 备份导入 | 在线迁移不可用或风险过高 |
在线迁移的“割接时刻”:最容易出事故的地方
在线迁移不是难在“同步”,而是难在“切换”。事故通常来自一个词:冲突(双写、主键冲突、覆盖更新、逻辑状态错乱)。
割接最小闭环(建议当作 Checklist):
- 停写(冻结源库写入):维护模式/网关断流/停应用都可以,关键是“确认真的没有写入”
- 追平增量:等待/触发同步延迟收敛到可接受范围(最好是 0 或接近 0)
- 最终校验:抽样校验不够的话,做校验和或表级对账
- 切连接:配置批量切换,保证一次性生效
- 恢复写入与观测:确认新流量只写目标库,监控错误率、延迟、关键指标
- 保留回退路径:源库先只读保留一段观察期,再决定退役
一致性校验的例子(MySQL):
pt-table-checksum --nocheck-replication-filters --databases=dbname h=src_host
如果你确实在割接前让应用同时写源库与目标库(即“双写”),除非你有明确的冲突解决策略(例如幂等写、业务层去重、统一序列号与严格顺序保证),否则迁移工具一般救不了你。
经验与避坑:把风险提前“锁死”
在线迁移(DTS/CDC)常见优化点
- 先预演再上生产:至少跑通一次“全量 + 增量 + 割接 + 回退”的全链路演练
- 限速与资源隔离:全量阶段要避免压垮源库;目标库要留出足够写入与索引构建能力
- 监控与告警:同步延迟、失败重试、目标库写入错误、源库日志增长与保留期
- 迁移对象最小化:先迁必要库/表,减少第一次割接的不确定性
备份导入常见优化点
- 并行化优先:大多数时候瓶颈在导入,优先选择支持并行恢复的工具链
- 物理备份更稳:超大库更建议快照/物理备份(例如 Xtrabackup),避免逻辑导入“跑到一半失败”
- 传输别靠运气:专线/对象存储直传/断点续传能力,往往比“scp 一把梭”可靠
- 拆分策略:按业务域或时间范围分批迁移,减少单次失败的爆炸半径
两种方案都要做的事情
- 权限:源库读 + 日志访问;目标库写;提前验证而不是割接时临时加权限
- 容量与性能:CPU/内存/IOPS/磁盘空间,建议预留余量(例如 30%+),并确保参数与连接数上限匹配
- 回退:写清楚“什么时候回退、怎么回退、回退要做哪些清理”,并预留执行时间
- 沟通:迁移窗口、影响范围、冻结策略、负责人与应急联系人
总结:选择一条你能“稳定执行”的路线
- 如果你要的是 最小停机 + 可扩展到大库,在线迁移(DTS/CDC)更合适,但成功依赖严格割接流程与可观测性。
- 如果你有 明确维护窗口 + 数据规模可控,停机备份导入往往更稳、更省心,关键在于并行化与演练。
最终决定不在 PPT 上,而在你能否把“停写、校验、切换、回退”四件事做成一套可重复的流程。