4. 迁移风险评估与回滚策略
迁移工程真正难的并不是“把数据搬过去”,而是“搬错了还能不能退回来”。在动手之前,必须先把风险讲清楚:哪些环节可能丢数据、哪些操作会让业务停摆、哪些变化会让性能悄悄退化。只有把这三类风险识别到位,回滚点、备份与恢复预案才有设计依据,而不是事后补救。
一、三类核心风险的识别方法
数据丢失风险通常来自四个位置:源端在迁移窗口内仍在写入、增量同步的断点丢失、目标端唯一索引冲突导致文档被跳过、以及迁移脚本对字段类型做了隐式转换。识别方法是做一次“字段级差异盘点”:对每个集合统计源端与目标端的文档数、各字段的缺失率、类型分布。例如某订单集合源端 amount 为 Decimal128,若目标端被写成 Double,金额精度就会在聚合时出现偏差,这类问题不会报错,只会静默失真。
业务中断风险取决于切换方式。停机迁移的中断时间等于“最后一次全量 + 增量追平 + 校验”的总时长;双写或变更流(Change Stream)方案的中断时间只等于“切读流量”的瞬间,但复杂度更高。识别时要明确一个关键量:可接受中断窗口(RTO)。若业务只允许 5 分钟不可写,那么任何需要 30 分钟全量校验的方案都不可行,必须改为分批校验或后台校验。
性能退化风险最容易被忽略。常见诱因包括:目标端缺少源端已有的复合索引、分片键选择导致数据倾斜、新版本 MongoDB 的默认读关注(readConcern)或写关注(writeConcern)变化、以及 WiredTiger 缓存与工作集不匹配。识别手段是在预演环境用真实查询回放,对比 explain("executionStats") 中的 totalDocsExamined 与 executionTimeMillis。若某查询在源端走索引、在目标端变成 COLLSCAN,就是明确的退化信号。
二、回滚点怎么设:四个锚点
回滚点不是“备份一下”这么简单,它必须是一个可定位、可重放、可验证的时间锚点。工程上通常设四个:
- R0 迁移前快照:用
mongodump --oplog在源端生成一致性快照,同时记录当时的 oplog 时间戳ts。这是最后的兜底,代价是恢复慢。 - R1 增量追平点:记录 Change Stream 的
resumeToken或 oplog 位点。一旦目标端数据异常,可以从该点重新拉取增量,而不必全量重来。 - R2 校验通过点:文档数、抽样字段哈希、关键聚合结果三者一致后打标。只有过了 R2,才允许进入切读阶段。
- R3 切读完成点:连接串切换后,保留源端只读一段时间,作为“热备回退位”。
四个锚点的价值在于:越靠后的回滚点,恢复代价越小。如果问题在 R2 之前发现,直接回退到 R0 即可;如果问题在切读后才发现,优先用 R3 把流量切回源端,再决定是否修复目标端。
三、备份与恢复预案的落地要点
备份要区分“逻辑备份”和“物理备份”。逻辑备份用 mongodump,跨版本兼容性好,但大库恢复慢;物理备份直接复制 WiredTiger 文件,恢复快,但要求版本与存储引擎一致。迁移场景建议两者都做:R0 用物理备份保证恢复速度,同时用逻辑备份做字段级校验。
# R0 一致性快照(示例)
mongodump --host rs0/src:27017 \
--db order_db \
--oplog \
--gzip \
--out /backup/r0_20250601
# 记录快照对应的 oplog 位点
mongosh --host rs0/src:27017 --eval \
'db.getSiblingDB("local").oplog.rs.find().sort({$natural:-1}).limit(1).pretty()'
恢复预案必须写成可执行的步骤,而不是一句“恢复备份”。一个可用的预案至少包含:触发条件(如校验差异率 > 0.1%)、决策人、恢复顺序(先停写 → 恢复 R0 → 重放 oplog 到 R1 → 校验 → 切回)、以及每一步的验证命令。特别要注意恢复后的写关注:如果源端原本是 w:"majority",恢复后不能降级为 w:1,否则会引入新的数据丢失窗口。
易错点:很多团队只备份了数据,却忘了备份索引定义、分片配置、用户与角色。恢复时数据回来了,但索引缺失导致查询全表扫描,业务照样不可用。建议在 R0 阶段一并导出 db.getCollectionInfos() 与 sh.status() 的结果。
四、把风险变成可判断的指标
风险不能只停留在定性描述。建议在迁移前为每类风险定义阈值,并在预演中实测:数据丢失用“文档数差异率”和“字段类型不一致数”衡量;业务中断用“实际切换耗时 vs RTO”衡量;性能退化用“P95 查询延迟增幅”和“COLLSCAN 查询占比”衡量。只有这些指标在预演中全部达标,才允许进入正式迁移窗口。回滚策略的最终形态,是一份带阈值、带命令、带责任人的预案,而不是一段口头承诺。