怎样在数据库迁移中最小化停机时间?

wen IT资讯 238

本文目录导读:

怎样在数据库迁移中最小化停机时间?

  1. 策略一:主从复制 + 主从切换(最常用,停机时间 < 1分钟)
  2. 策略二:双写模式(停机时间 < 5分钟,但复杂度高)
  3. 策略三:影子表 + 在线DDL(适用于表结构修改,停机时间 < 1分钟)
  4. 策略四:蓝绿部署 + DNS切换(适用于云原生环境,停机时间 < 10秒)
  5. 关键实战建议(减少意外停机时间)
  6. 最佳选择

在数据库迁移中最小化停机时间,核心思路是将“全量迁移”与“增量同步”分离,让大多数工作在在线状态下完成,仅在最后切流时进行短暂的“真正”停机。

以下是几种成熟的、经过业界验证的策略,按停机时间从数分钟到秒级排列:

主从复制 + 主从切换(最常用,停机时间 < 1分钟)

这是目前最主流、对应用层侵入最小的方案,适用于 MySQL、PostgreSQL 等支持物理日志复制的数据库。

步骤:

  1. 搭建从库(在线,无停机): 在新数据库上搭建一个从库,从旧主库同步数据,此时旧主库依然对外服务。
  2. 增量同步(在线): 从库持续解析旧主库的 Binlog(MySQL)或 WAL(PostgreSQL),实时追平数据,可以使用 mysqldumppg_dump 进行全量初始同步,然后开启持续复制。
  3. 数据校验与核对(在线): 定期从应用层校验旧主库与从库关键数据的一致性(例如记录数、Checksum)。
  4. 切换前准备(在线):
    • 停掉旧主库上的写操作(例如停应用、或设置数据库只读)。
    • 等待从库追平最后几秒的增量延迟。
  5. 切换(秒级停机):
    • 将从库提升为主库。
    • 修改 DNS、配置中心(如 Consul/Nacos)、或应用层的数据库连接池(最关键一步),指向新库。
    • 重启应用或等待连接池刷新。
  6. 回滚预案: 保留旧主库,如果新库有问题,将应用指回旧主库。

特点: 停机时间取决于DNS缓存刷新或连接池重连时间,几秒到几十秒

双写模式(停机时间 < 5分钟,但复杂度高)

适用于无法使用原生复制工具的场景(不同数据库类型迁移,Oracle -> MySQL,或需要大规模修改表结构)。

步骤:

  1. 全量迁移(离线或在线): 先批量将旧库的历史数据导入新库。
  2. 开启双写(在线): 修改应用代码,对任何写操作(Insert/Update/Delete),先写新库,再写旧库(或反之,但需处理幂等和失败补偿)。
    • 难点1: 必须保证新旧库写操作的最终一致性,旧库写入失败需有重试或死信队列。
    • 难点2: 读取请求依然从旧库读。
  3. 增量同步(在线): 双写模式相当于应用自己做了实时同步。
  4. 数据校验与回填(在线): 对比新旧库,将有差异或缺失的历史数据补上。
  5. 切换(短停机):
    • 确认双写稳定运行一段时间(例如12小时)后。
    • 短暂停应用(或阻塞网络层)。
    • 确保双写最后一批数据完全同步。
    • 切换读请求 从旧库指向新库。
    • 移除旧库的写入逻辑,仅保留新库写入。
  6. 回滚预案: 若切换后有问题,将读请求切回旧库,继续双写模式。

特点: 停机时间很短(几秒),但工程复杂度极高(要求应用层代码无状态、可重入、容错性好),适合有专职中间件团队的场景。

影子表 + 在线DDL(适用于表结构修改,停机时间 < 1分钟)

如果你需要迁移并同时修改表结构(如加字段、改索引),直接用 ALTER TABLE 可能导致大表锁表数小时,可以使用 MySQL 的 gh-ost 或 Percona的 pt-online-schema-change

步骤:

  1. 创建影子表: 直接在原数据库上创建一个与旧表结构类似但包含新修改的影子表。
  2. 触发器或日志读取: 工具会在旧表上创建三个触发器(Insert/Update/Delete),将旧表上的实时变更同步到影子表。
  3. 全量拷贝: 工具将旧表的历史数据逐块拷贝到影子表。
  4. 追平增量: 触发器持续工作,直到影子表数据非常接近旧表。
  5. 切换(原子操作):
    • 工具执行 RENAME TABLE old_table TO old_table_bak, shadow_table TO old_table,这是一个内部元数据操作,几乎瞬间完成(毫秒级)。
    • 应用完全无感知,表名没变,但底层的物理文件已指向了新表。

特点: 非常适合在不改表名、不改连接配置的情况下修改表结构。

蓝绿部署 + DNS切换(适用于云原生环境,停机时间 < 10秒)

如果架构上允许,可以配置两套独立的数据库环境和服务实例。

步骤:

  1. 准备环境: 搭建一个与生产环境(蓝环境)完全一致,但指向新数据库的“绿环境”服务集群。
  2. 数据同步(在线): 通过 CDC(Change Data Capture,如 Debezium / Canal)将蓝库的变更实时推送到绿库。
  3. 预验证(在线): 提前启动绿环境的服务(但未接入流量),专门跑一下健康检查和冒烟测试。
  4. 切换(秒级):

    修改负载均衡器(如 Nginx / HAProxy / AWS ELB)的流量权重,将流量从100%蓝平滑切换至100%绿。

  5. 回滚: 如果出错,立即将流量切回蓝环境。

特点: 切换时间完全取决于DNS / Load Balancer 的生效时间(通常秒级),且不影响任何已有连接。


关键实战建议(减少意外停机时间)

  1. 不要依赖慢速工具: 避免使用 mysqldump 直接导大表,优先使用物理备份工具(如 XtraBackup)。
  2. 提前压测增量同步能力: 在迁移前,观察旧库的写QPS(每秒查询率),如果旧库每秒有2万次写入,你的CDC或双写机制必须能处理3万次以上,否则会持续积压。
  3. 监控延迟: 实时监控复制或同步延迟,如果延迟 > 5秒(对100ms同步而言),需要立刻分析瓶颈(通常是磁盘IO或网络带宽)。
  4. 做一次演练: 在正式迁移前,在低峰期(如凌晨)做一次 “预切换” ,测试DNS解析变化后的连接恢复时间,以及应用是否因连接池扔出错误而瘫痪。
  5. 保留旧配置: 迁移完成后,保留旧库1-2周,不要立刻删除,经常有迁移后1天发现数据完整性问题,需要回滚。
  6. 选对工具:
    • 异构数据库(如 Oracle -> MySQL / MongoDB):推荐使用 Debezium(CDC)+ Kafka 解耦。
    • 同构大表:直接使用 原生复制(Strategy 1) 最稳。
    • 小表但有复杂结构修改:直接使用 gh-ost(Strategy 3)

最佳选择

  • 如果只是版本升级或水平扩展(同构):主从复制 + 主从切换(策略一),这是难度最低、成功率最高的方式。
  • 如果需要改表名或结构(同库):gh-ost(策略三)
  • 如果必须跨数据库类型(异构):双写模式(策略二)CDC(策略四变种)
  • 如果需要业务完全无感知回滚:蓝绿部署(策略四)

核心原则: 永远不要在迁移过程中“先删旧库,再建新库”。增量同步是安全的基石,原子切换是节拍器。

抱歉,评论功能暂时关闭!