本文目录导读:

- 策略一:主从复制 + 主从切换(最常用,停机时间 < 1分钟)
- 策略二:双写模式(停机时间 < 5分钟,但复杂度高)
- 策略三:影子表 + 在线DDL(适用于表结构修改,停机时间 < 1分钟)
- 策略四:蓝绿部署 + DNS切换(适用于云原生环境,停机时间 < 10秒)
- 关键实战建议(减少意外停机时间)
- 最佳选择
在数据库迁移中最小化停机时间,核心思路是将“全量迁移”与“增量同步”分离,让大多数工作在在线状态下完成,仅在最后切流时进行短暂的“真正”停机。
以下是几种成熟的、经过业界验证的策略,按停机时间从数分钟到秒级排列:
主从复制 + 主从切换(最常用,停机时间 < 1分钟)
这是目前最主流、对应用层侵入最小的方案,适用于 MySQL、PostgreSQL 等支持物理日志复制的数据库。
步骤:
- 搭建从库(在线,无停机): 在新数据库上搭建一个从库,从旧主库同步数据,此时旧主库依然对外服务。
- 增量同步(在线): 从库持续解析旧主库的 Binlog(MySQL)或 WAL(PostgreSQL),实时追平数据,可以使用
mysqldump或pg_dump进行全量初始同步,然后开启持续复制。 - 数据校验与核对(在线): 定期从应用层校验旧主库与从库关键数据的一致性(例如记录数、Checksum)。
- 切换前准备(在线):
- 停掉旧主库上的写操作(例如停应用、或设置数据库只读)。
- 等待从库追平最后几秒的增量延迟。
- 切换(秒级停机):
- 将从库提升为主库。
- 修改 DNS、配置中心(如 Consul/Nacos)、或应用层的数据库连接池(最关键一步),指向新库。
- 重启应用或等待连接池刷新。
- 回滚预案: 保留旧主库,如果新库有问题,将应用指回旧主库。
特点: 停机时间取决于DNS缓存刷新或连接池重连时间,几秒到几十秒。
双写模式(停机时间 < 5分钟,但复杂度高)
适用于无法使用原生复制工具的场景(不同数据库类型迁移,Oracle -> MySQL,或需要大规模修改表结构)。
步骤:
- 全量迁移(离线或在线): 先批量将旧库的历史数据导入新库。
- 开启双写(在线): 修改应用代码,对任何写操作(Insert/Update/Delete),先写新库,再写旧库(或反之,但需处理幂等和失败补偿)。
- 难点1: 必须保证新旧库写操作的最终一致性,旧库写入失败需有重试或死信队列。
- 难点2: 读取请求依然从旧库读。
- 增量同步(在线): 双写模式相当于应用自己做了实时同步。
- 数据校验与回填(在线): 对比新旧库,将有差异或缺失的历史数据补上。
- 切换(短停机):
- 确认双写稳定运行一段时间(例如12小时)后。
- 短暂停应用(或阻塞网络层)。
- 确保双写最后一批数据完全同步。
- 切换读请求 从旧库指向新库。
- 移除旧库的写入逻辑,仅保留新库写入。
- 回滚预案: 若切换后有问题,将读请求切回旧库,继续双写模式。
特点: 停机时间很短(几秒),但工程复杂度极高(要求应用层代码无状态、可重入、容错性好),适合有专职中间件团队的场景。
影子表 + 在线DDL(适用于表结构修改,停机时间 < 1分钟)
如果你需要迁移并同时修改表结构(如加字段、改索引),直接用 ALTER TABLE 可能导致大表锁表数小时,可以使用 MySQL 的 gh-ost 或 Percona的 pt-online-schema-change。
步骤:
- 创建影子表: 直接在原数据库上创建一个与旧表结构类似但包含新修改的影子表。
- 触发器或日志读取: 工具会在旧表上创建三个触发器(Insert/Update/Delete),将旧表上的实时变更同步到影子表。
- 全量拷贝: 工具将旧表的历史数据逐块拷贝到影子表。
- 追平增量: 触发器持续工作,直到影子表数据非常接近旧表。
- 切换(原子操作):
- 工具执行
RENAME TABLE old_table TO old_table_bak, shadow_table TO old_table,这是一个内部元数据操作,几乎瞬间完成(毫秒级)。 - 应用完全无感知,表名没变,但底层的物理文件已指向了新表。
- 工具执行
特点: 非常适合在不改表名、不改连接配置的情况下修改表结构。
蓝绿部署 + DNS切换(适用于云原生环境,停机时间 < 10秒)
如果架构上允许,可以配置两套独立的数据库环境和服务实例。
步骤:
- 准备环境: 搭建一个与生产环境(蓝环境)完全一致,但指向新数据库的“绿环境”服务集群。
- 数据同步(在线): 通过 CDC(Change Data Capture,如 Debezium / Canal)将蓝库的变更实时推送到绿库。
- 预验证(在线): 提前启动绿环境的服务(但未接入流量),专门跑一下健康检查和冒烟测试。
- 切换(秒级):
修改负载均衡器(如 Nginx / HAProxy / AWS ELB)的流量权重,将流量从100%蓝平滑切换至100%绿。
- 回滚: 如果出错,立即将流量切回蓝环境。
特点: 切换时间完全取决于DNS / Load Balancer 的生效时间(通常秒级),且不影响任何已有连接。
关键实战建议(减少意外停机时间)
- 不要依赖慢速工具: 避免使用
mysqldump直接导大表,优先使用物理备份工具(如 XtraBackup)。 - 提前压测增量同步能力: 在迁移前,观察旧库的写QPS(每秒查询率),如果旧库每秒有2万次写入,你的CDC或双写机制必须能处理3万次以上,否则会持续积压。
- 监控延迟: 实时监控复制或同步延迟,如果延迟 > 5秒(对100ms同步而言),需要立刻分析瓶颈(通常是磁盘IO或网络带宽)。
- 做一次演练: 在正式迁移前,在低峰期(如凌晨)做一次 “预切换” ,测试DNS解析变化后的连接恢复时间,以及应用是否因连接池扔出错误而瘫痪。
- 保留旧配置: 迁移完成后,保留旧库1-2周,不要立刻删除,经常有迁移后1天发现数据完整性问题,需要回滚。
- 选对工具:
- 异构数据库(如 Oracle -> MySQL / MongoDB):推荐使用 Debezium(CDC)+ Kafka 解耦。
- 同构大表:直接使用 原生复制(Strategy 1) 最稳。
- 小表但有复杂结构修改:直接使用 gh-ost(Strategy 3)。
最佳选择
- 如果只是版本升级或水平扩展(同构): 选 主从复制 + 主从切换(策略一),这是难度最低、成功率最高的方式。
- 如果需要改表名或结构(同库): 选 gh-ost(策略三)。
- 如果必须跨数据库类型(异构): 选 双写模式(策略二) 或 CDC(策略四变种)。
- 如果需要业务完全无感知回滚: 选 蓝绿部署(策略四)。
核心原则: 永远不要在迁移过程中“先删旧库,再建新库”。增量同步是安全的基石,原子切换是节拍器。