数据库迁移、切割checklist
数据库迁移与切库 Checklist:我如何降低一次迁移的风险
数据库迁移不是简单修改连接串,应该把它当成一次有阶段、有验证、有回滚的工程操作:先同步数据,再切读流量,最后切写流量,并在旧库下线前完成连接核查和数据归档。
背景
我在做数据库迁移时,最担心的不是“切不过去”,而是“切过去以后才发现问题”:数据不一致、SQL 变慢、同步延迟超标、还有系统偷偷连着旧库。
所以我不会把数据库迁移设计成一次性动作。更稳妥的方式是把风险拆开:先让新库具备完整数据,再让新库承担读流量,最后再把写流量切过去。每个阶段都有明确的验证标准,出问题时也更容易回退。
整体流程可以概括为:
一、迁移前先定边界
开始导数据之前,我会先确认迁移范围。这个步骤看起来慢,但能避免后面反复补洞。
我通常会列清楚这些内容:
| 项目 | 需要确认的内容 |
|---|---|
| 系统范围 | 哪些应用、任务、报表、脚本访问旧库 |
| 表范围 | 哪些表迁移,哪些表保留,哪些表只读 |
| 接口范围 | 哪些接口读库,哪些接口写库,哪些接口读写混合 |
| 数据范围 | 是否全量迁移,历史数据是否归档,是否有过滤规则 |
| 时间窗口 | 是否允许短暂停写,是否有业务低峰期 |
| 回滚条件 | 读切换如何回滚,写切换后是否还能回滚 |
我还会提前定义成功标准,而不是只写“迁移完成”。比如:
- 新旧库核心表行数一致,差异可解释。
- 关键业务字段校验通过。
- 增量同步延迟低于业务阈值。
- 新库核心 SQL 延迟不高于迁移前基线。
- 切换后接口错误率没有明显升高。
- 旧库连接数逐步归零。
这些标准越具体,切换当天的判断就越少依赖感觉。
二、新库初始化与增量同步
第一个正式阶段,是让新库先拥有完整数据。此时旧库仍然承担读写,新库只负责接收历史数据和增量变更。
存量数据可以通过备份恢复、导出导入、同步工具等方式完成。大表我一般会按主键范围或时间分片迁移,避免一次性全表扫描影响旧库。
存量导入完成后,还要接上增量同步。不同数据库有不同方案,例如 MySQL 可以基于 binlog,Oracle 可以使用 OGG,PostgreSQL 可以基于 logical replication 或 WAL 解析。方案本身不是重点,关键是要确认同步链路是否具备这些能力:
- 支持断点续传。
- 支持失败重试。
- 重复事件可以幂等处理。
- 删除、更新、乱序事件处理符合预期。
- 同步延迟可监控、可告警。
数据校验我一般分三层做:
| 层级 | 校验方式 | 目的 |
|---|---|---|
| 粗粒度 | 表行数、分区行数 | 发现明显漏数 |
| 中粒度 | checksum、关键字段聚合 | 发现批量差异 |
| 细粒度 | 抽样业务对账 | 发现业务语义差异 |
checksum 不能替代业务对账。订单金额、账户余额、库存状态这类数据,最终还是要按业务口径再核一次。
在进入下一阶段前,我会要求存量导入完成、增量同步稳定、核心表校验通过,并确认新库的表结构、索引、容量和权限都已经检查过。
三、先切读流量
我习惯先切读,再切写。原因很简单:读流量通常更容易回滚,而且能提前暴露新库的查询性能、索引缺失和同步延迟问题。
切读之前,应用层最好具备读路由能力,至少可以通过配置控制读请求走旧库还是新库。灰度比例不要一步到位,可以从小流量开始,例如 1%、5%、10%、30%,观察稳定后再扩大。
这一阶段最容易忽略的是“读己之写”。如果旧库仍然承接写入,新库承担读取,那么用户刚写完数据后立刻查询,可能因为同步延迟读不到最新结果。对强一致场景,我会让写后短时间内继续读旧库;对后台查询或报表类场景,可以接受最终一致,但必须监控同步延迟。
切读期间我重点看这些指标:
- 新库 QPS、连接数、CPU、IO、内存。
- 慢 SQL 数量和接口延迟。
- 接口错误率、超时率。
- 新旧库查询结果差异。
- 增量同步延迟。
- 旧库读流量是否按预期下降。
只有当读流量稳定、新库性能达标、没有不可解释的数据差异时,我才会考虑进入写切换。
四、再切写流量
写切换是风险最高的一步。因为新库开始承接写入后,数据主权就变了,回滚成本会明显增加。
如果业务允许,我更倾向使用短暂停写窗口:先停止旧库写入,等待增量同步追平,再做最后一次数据校验,然后把写连接切到新库。这个方式虽然需要窗口,但链路清晰,风险可控。
如果业务不允许停写,就需要双写或补偿方案。但我不会轻易把“双写”当成默认答案,因为它会引入重复写、部分成功、顺序错乱、冲突处理等新问题。只要使用双写或 CDC 回放,就必须提前设计幂等策略,确保失败重试不会造成多写或脏写。
切写完成后,我不会马上下线旧库,而是保留观察窗口。观察重点包括:
- 新库写入错误率。
- 主键冲突、唯一键冲突。
- 事务失败、锁等待、慢 SQL。
- 旧库是否还有非预期写入。
- 核心业务对账是否正常。
回滚方案必须在切写前写清楚。读切换通常可以直接切回旧库;写切换后如果已经产生新数据,回滚就可能需要停写、对账、反向修复,再恢复旧库入口。没有回滚方案,我不会贸然切写。
五、旧库核查与下线
切库完成不等于迁移结束。很多问题都出现在“以为已经没人用旧库”的时候。
旧库下线前,我会重点核查这些连接来源:
- 业务应用是否仍连接旧库。
- 定时任务是否仍访问旧库。
- 报表、BI、导出脚本是否仍依赖旧库。
- 运维脚本或临时脚本是否写死旧库地址。
- 第三方系统是否还有旧库账号。
确认没有非预期连接后,我会把旧库先冻结为只读,再做完整备份和恢复验证。只有在业务、研发、运维、数据库负责人都确认后,才进入最终归档和下线流程。
我的简化 Checklist
迁移前
同步阶段
切换阶段
下线阶段
总结
我理解的数据库迁移,本质不是搬数据,而是控制变化。
一套可靠的迁移流程,至少要做到三点:第一,每个阶段都有明确的入口和出口标准;第二,关键风险都有监控指标和告警;第三,每次切换前都知道失败后怎么退。
只要把同步、校验、灰度、回滚和旧库下线这些环节设计清楚,数据库迁移就不再依赖临场经验,而可以变成一套可演练、可复用、可持续改进的工程流程。

浙公网安备 33010602011771号