← 每日面试题 学习看板

如何做平滑的数据迁移?

面试题/01实践场景题/实践场景题目/系统设计与架构/如何做平滑的数据迁移?.md

面试记录 2026-10-14

题目:如何做平滑的数据迁移?

难度:medium

标签:practice/architecture, architecture/migration

评分:⭐⭐⭐⭐⭐(5/5)

我的回答

数据迁移想要平滑的,是大家所有人的目标。但是这个是否能达到,其实很难。

涉及的问题首先是双库的并行,然后数据同步的规则,然后切换节点业务是否要停机。

不停机的过程中产生的数据如何进行同步?双库之间互相之间在不同的节点都产生数据,如何互相同步?都是相应存在相应问题的。

我们之前做过几次数据库迁移,基本上都是大动干戈,而且产生了很多问题。有收获,但是也没有能完全解决。 数据库迁移,首先你要考虑的就是,你从这个数据库迁到另一个库,你的目的是什么?解决压力问题,还是更换存储介质,还是什么原因?相互之间所有的功能都能兼容吗?前置的这都需要调研。之前我们只是从 5.5 MySQL 5.5 升到 5.升到 5.8,都中间遇到了不少问题。默认的一些配置,迁过去测试环境整个就瘫了,一些配置之前的语法是不支持的。你只有对默认配置进行重新设置,之前写的一些东西才能支持。这个过程中你要做完善的测试,各种功能你需要测试到,否则就会产生各种意外。

书归正题,平滑迁移,首先你要确定相互之间的兼容性,你迁移过后可以兼容,所有功能原地保留。然后,这个其实你可以在测试环境验证,先搭一个子环境,把整个数据迁过去,做一个验证。

确认没有问题,然后才走下一步,是否要用这个。

过程基本上分两步骤,历史数据全量同步。基本上会在把历史数据全量的迁移过去,然后保留近期的一个,从一个时间节点近期的一个数据,做保留,之前的数据全部同步过去,全量的同步过去,后边的数据开始做增量同步。这样确保时间的稳定。

数据同步由增量同步跟全量同步有很多工具。我们当时用的是阿里的 DataX,然后它有直接的支持。这个迁移的过程,你要考虑你迁移数据的时候对原有库的压力。当时我们设了很高的并发,导致直接就崩了。直接线上业务就崩溃了。然后很及时的处理了,但是业务也宕了大概有半个小时,产生了直接的问题影响,这是当时没有预料到的。

增量同步完了全量同步完了之后,开始做增量的双向同步。这时候你可能会做一些需要做一些灰度。微服务下,有些服务使用老库,有些服务使用新库。然后数据可能会存在延迟。双向增量同步就是 A 库 A 服务写到老库,A1 服务写到新库,然后 A1 跟 A 服务之间的数据同步。这个都是会产生不同的影响的,看你业务是否会有这方面影响。如果没有还好,有的话需要考虑双写,同一份数据写两个库,同时写。

库并行执行了一段时间之后,然后再考虑单写,把老库的数据写入移除,只写入新库。这时候老库还要保留一段时间,防止新库出现问题,没法有冗余,需要做一个冗余。

最后执行完成之后,看整个要对整个库新库做压力测试,看是否能满足正常的业务需求。这个过程其实是在灰度的过程中执行的。线上服务有一部分走老库,一部分走新库,然后对外提供查的支持跟写的支持。写当时是双写,然后一部分库读从老库读,一部分库从新库读,然后对比压力情况,服务是否能正常使用,以及效率是否存在问题,这个都是要进行考虑的。

整个迁移完成之后,老库还要保持保留一段时间,从一个时间节点记录好。然后后边的数据都新库读新库写,但是新库的数据同步回老库,确保老库的数据不丢失。在这个过程中,有迭代也不要改数据库,不要增表、改表,这个要和业务侧说清楚,因为在业务侧执行过程中,执行迁库这个操作,你再改表,会产生很多不可预料的问题。

整个流程大概就是这样。先验证,在测试环境验证服务的数据库新数据库的可用性,所有东西都兼容。然后做数据的增量、全量同步,全量同步完成之后做增量同步,增量同步之后验证灰度,验证部分服务的性能,在新库上是否可以正常使用。然后增量的过程中,同时新增数据的话做双写,同时往两个库写,保证业务的可用性。然后当整个服务迁完之后,用老库先保留一个月到两个月,然后增量的把新库的数据同步回老库,防止业务出现问题,无法正常使用。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:考察"零停机数据迁移"的完整方法论——从架构设计到工程落地到回滚预案。

知识点拆解:

  1. 迁移目标明确:先回答"为什么迁"(容量/性能/技术栈升级/拆分),不同目标方案不同
  1. 迁移阶段(六步法):
  1. 数据一致性保障:
  1. 回滚预案:
  1. 工程细节:

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. Canal 是怎么做到基于 binlog 的增量同步的?
  1. 迁移过程中如何保证数据一致性?
  1. 如果迁移过程中新库挂了,怎么回滚?

第三部分:面试者参考回答(三步法口语化,300-400 字)

【一句话结论】

面试官您好,平滑迁移的核心是"双写 + 灰度 + 反向同步"三件套,本质是把"一次性切换"拆成"渐进式切流",每一步都可验证、可回滚。

【三点展开】

第一,先验证再迁移:搭测试环境子库,跑全量 SQL 兼容性测试(特别是 MySQL 5.7→8.0 这种大版本升级,语法/配置/驱动都可能不兼容)。我们踩过坑:MySQL 5.5 升到 5.8,测试环境整个瘫了,因为默认配置不兼容旧语法,重新调配置才恢复。

第二,迁移分六步走:兼容性验证 → 全量同步(DataX,限流防打爆老库)→ 增量同步(Canal/Debezium 基于 binlog)→ 双写灰度(应用层双写 + 读写分离,DNS 权重 1%→10%→50%→100%)→ 单写切换(只写新库)→ 回滚期(老库保留 1-2 个月)。每步都有校验:全量后抽样对比、增量后延迟监控、切换后业务指标对齐。

第三,回滚预案是兜底:老库保留 + 新库→老库反向同步(binlog 同步),切回前校验新库数据完整性,DNS/负载均衡权重秒级切回老库。迁移期间跟业务侧约定不改表(增表/改表会破坏同步),这是踩坑后血泪教训。

【一句边界】

当然,如果是小表(< 100 万行)一次性迁移,直接停机 + mysqldump 就行,不必走这套流程——KISS 原则,能用简单方案解决的别引入 Canal/DTS 这种复杂组件。