跳转到主要内容
AG·SORA
技术

业务应用的零停机数据库迁移:扩展—迁移—收缩模式、回填与回滚计划

发布于 10 分钟阅读作者:agsora.tech
AG·SORA / BLOGAG·SORA技术业务应用的零停机数据库迁移:扩展—迁移—收缩模式、回填与回滚计划agsora.tech
本文目录

每一个持续运行的业务应用都会发生变化。新功能需要新字段,新报表需要新表,数据增长迫使旧结构重新整理。问题在于,数据库是应用中最难在使用过程中修改的部分。程序代码可以在几秒钟内通过重新发布来替换,但一张存有数百万行订单、发票和库存记录的表,不可能“暂时关掉一会儿”而不产生后果。许多企业最终选择半夜的维护窗口,或者更糟——一直拖延变更,直到技术债堆积如山。

本文介绍如何以最小风险、并尽可能不停止服务的方式修改业务应用的数据库结构:渐进式变更模式、如何迁移大量数据、回滚计划以及测试。本文面向需要理解变更背后技术决策的企业主和产品经理,也面向寻找实用框架的技术团队。

摘要

  • 安全的数据库变更应采用“扩展、迁移、收缩”的渐进模式,而不是一次性替换
  • 在触碰生产数据之前,务必准备回滚计划和已验证可恢复的备份
  • 在后台分小批迁移大量数据,避免锁表和拖慢用户
  • 在生产数据的副本上测试迁移、测量耗时,并在正式日期之前演练流程
  • 向业务用户沟通时间安排与风险;并非每次变更都需要零停机,但每次变更都需要有计划
插在配线架上的蓝色和灰色网线
对数据层的变更应像对物理基础设施的变更一样提前规划

为什么数据库迁移有风险

数据库结构变更与代码变更有两点不同:数据是永久的,而且变更往往一次影响整个应用。

  • **数据无法“替换”**:代码错误可以通过新版本修复,但损坏或被删除的数据只能从备份中恢复
  • **锁表**:某些结构变更在执行期间会锁住表,导致应用等待或报错
  • **版本兼容性**:发布期间,新旧版本的代码可能同时运行,两者都必须与数据库结构匹配
  • **规模**:在测试数据上一秒完成的变更,在生产数据上可能需要一小时
  • **隐藏的依赖**:报表、集成和旧脚本可能正在读取您打算修改的字段

因此,数据库迁移应被视为一个有准备、有测试、有退路的小项目,而不是顺手完成的日常任务。

基本原则:扩展、迁移、收缩

实现零停机变更最常用的模式通常称为“expand and contract”(扩展与收缩)。其思想是:永远不要以会让旧版本代码立刻崩溃的方式去修改东西。

第 1 阶段:扩展

在不删除旧结构的前提下添加新结构。例如,想把“全名”字段拆分为名和姓,先添加两个新字段。旧字段保留,仍在使用。添加可选字段通常既快又安全。

第 2 阶段:迁移

修改应用,使其同时写入新旧结构,然后把历史数据逐步从旧结构复制到新结构。当所有数据都已复制且一致后,再把应用改为从新结构读取。在整个过程中,两个版本的代码都能正常工作。

第 3 阶段:收缩

确认没有任何东西再使用旧结构之后,停止向它写入,然后在后续版本中删除旧字段或旧表。不要着急:把旧结构保留一段时间作为安全网。

这种模式比一次性修改需要更多步骤,但每一步都很小、可逆,并且不会中断服务。它与功能开关与渐进式发布相配合,使切换到新行为的风险较低。

变更类型与风险等级

并非所有变更都一样。认清风险等级,有助于判断是否需要维护窗口。

低风险变更

  • 添加旧代码尚未使用的新表
  • 添加不带繁重默认值的可选字段
  • 用不锁表的方法添加索引(在数据库引擎支持的情况下)

中等风险变更

  • 修改字段的数据类型,尤其是在大表上
  • 为拥有数百万行的表添加带默认值的必填字段
  • 对已有数据添加约束,因为旧数据必须经过校验

高风险变更

  • 重命名被应用多处使用的字段或表
  • 删除字段或表
  • 拆分或合并大表
  • 把数据库迁移到其他引擎或服务商

对于高风险变更,始终采用渐进模式。重命名应通过“添加新名称、复制、切换、再删除旧名称”来完成,而不是直接使用重命名命令。

在不打扰用户的情况下迁移大量数据

在一个大事务中复制数百万行,可能锁表、耗尽内存,并使数据库副本落后。更安全的做法是分小批填充数据(回填,backfill)。

安全的回填模式

  • **小批量**:每轮处理几千行,而不是一次几百万行
  • **轮次之间留间隔**:加入短暂停顿,使数据库对用户的负载保持较低
  • **可续跑**:记录最后位置,使中断的进程可以继续而不是从头开始
  • **幂等**:同一批次运行两次不会损坏数据
  • **监控**:运行期间关注应用响应时间、队列和复制延迟
  • **时机**:在非高峰时段运行,例如门店营业时间之外或月末结账之外

这种做法类似于事件驱动架构与消息队列中的后台处理:把繁重的工作拆分成可重试的小单元。

处理迁移期间到达的新数据

旧数据在被复制的同时,用户仍在不断创建新数据。要确保应用同时写入两种结构(双写),或使用变更捕获机制(触发器或变更日志),保证不遗漏任何一行。完成后进行一致性检查:新旧结构之间的行数、总金额和随机抽样必须一致。

回滚计划与备份

迁移之前最重要的问题是:“如果失败了,我们怎么回去?”没有明确答案的团队,还没有准备好进行迁移。

真正可以恢复的备份

有备份不等于有可恢复的备份。请在独立环境中测试恢复,并测量耗时。如果恢复需要六小时,那么一小时的维护窗口就毫无意义。完整策略见企业数据备份策略和灾难恢复与业务连续性规划。

“继续还是回滚”的决策点

提前设定会让您取消的标准:例如响应时间超过阈值、错误率上升或一致性检查失败。同时明确谁有权做出决定,避免在过程中陷入争论。

结构回滚与数据回滚

恢复结构比恢复数据容易。一旦用户已向新结构写入了新数据,回到旧结构就可能意味着丢失这些数据。这正是双写如此有帮助的原因:旧结构保持完整,因此在收缩阶段之前取消都是安全的。

正式日期之前的测试

未经测试的迁移就是赌博。请准备一个与生产环境相似的测试环境。

  • **生产数据副本**:使用副本(必要时对个人数据做脱敏),使耗时和行为接近真实情况
  • **测量耗时**:记录每个步骤的时间,并按数据增长进行外推
  • **测试两个版本的代码**:确保新旧版本在混合结构上都运行良好
  • **演练执行**:从头到尾运行整个流程,包括回滚
  • **自动化测试**:把迁移脚本纳入持续集成流程,参见[自动化测试与 CI/CD](/blog/pengujian-otomatis-dan-ci-cd-untuk-aplikasi-bisnis)
  • **用户验收测试**:让业务用户在试运行后检查报表和关键数字,与[应用上线前的 UAT](/blog/uat-pengujian-sebelum-aplikasi-diluncurkan)保持一致

大型迁移:更换数据库引擎或服务商

把数据库迁移到不同的引擎(例如从本地服务器迁移到云上托管服务,或从一种数据库类型迁移到另一种)是一个独立的类别。常见模式如下:

  • **持续复制**:把新数据库作为副本运行,始终追赶旧数据库
  • **并行验证**:连续几天比较两个数据库上重要查询的结果
  • **短暂切换**:在选定的时刻短暂暂停写入,确认副本与主库完全一致,然后把应用切换到新数据库
  • **待命期**:让旧数据库以只读模式保留一段时间,作为退路
  • **应用调整**:检查可能引发细微缺陷的行为差异(结果排序、时间处理、大小写敏感性)

战略层面的考虑以及依赖单一服务商的危险,见云与企业软件中的供应商锁定。对于包含数据在内的整体系统迁移,另见新系统的数据迁移准备和不停业的遗留系统现代化。

什么时候维护窗口反而更好

零停机并非绝对目标。对一些企业来说,有计划的维护窗口比复杂的渐进式设计更便宜、更安全。

  • 仅在工作时间使用、周末很安静的内部应用
  • 只需几分钟、针对小表的小改动
  • 非常复杂的一次性迁移,其中双写模式出错的风险超过其收益
  • 营业时间明确的企业,例如夜间打烊的门店

重要的是,窗口要提前公告、时间短,并且有回滚计划作为后盾。避免在销售高峰日不通知就突然维护。与业务日历同步:避开月末结账、发薪日和促销季。

业务团队与技术团队的协作

数据库迁移常被当作纯技术问题,但成功与否取决于协调。

  • **业务流程负责人**说明迁移后必须保持正确的报表和数字
  • **技术团队**用易懂的语言解释风险、耗时和选项
  • **客户支持**为可能出现的短暂中断做好应答准备
  • **数据负责人**批准一致性标准,例如总余额必须完全一致
  • **文档**记录改了什么、为什么改、如何回退,支持[技术文档与项目交接](/blog/dokumentasi-teknis-dan-serah-terima-proyek-software)

如果迁移的原因是数据库性能,也请查看数据库与业务应用变慢,因为问题往往可以通过更好的索引或查询解决,而无需大型迁移。

运行迁移前的简要清单

  • 存在最新备份,且已测试过恢复
  • 迁移脚本已在生产数据副本上运行过,耗时已知
  • 过渡期间新旧代码版本与结构兼容
  • 有书面回滚计划,含标准和责任人
  • 监控已就绪:响应时间、错误率、数据库负载
  • 时间安排已告知用户和客户支持
  • 迁移后的一致性检查已确定
  • 团队在执行期间及之后待命

常见问题

所有迁移都能做到零停机吗?

不是所有。很多变更可以渐进完成,但有些需要短暂停顿,例如最终切换到新的数据库引擎。目标是尽可能短、且有计划的停顿。

旧结构在删除之前应保留多久?

足够长,以确保没有报表、集成或脚本仍在使用它,通常是几周到一个财务结账周期。删除前先监控其使用情况。

仅为了迁移就需要修改应用吗?

通常需要,至少要在过渡期间兼容两种结构。团队应把这部分工作计入估算,而不是当作免费。

如果迁移后的数据不一致怎么办?

这正是一致性检查和待命期的作用。如果发现差异,停止切换,修复问题根源,然后重新来过。旧数据的质量也需要检查,参见数据质量与数据治理。

结论

修改正在使用的数据库,靠的是纪律,而不是勇气。借助“扩展—迁移—收缩”模式、小批量迁移数据、经过验证的备份以及在生产数据副本上的演练,大的变更可以拆解为一系列小而安全的步骤。如果无法做到零停机,就安排一个短暂、已公告、并留有退路的维护窗口。

在不影响运营的前提下规划数据库变更

Agsora 协助分阶段设计并实施数据库迁移和业务应用现代化,配有测试和清晰的回滚计划。请告诉我们您当前的系统情况,我们将提供初步方案。

免费咨询

免费清单:如何选择软件公司

签约前评估供应商的 24 个要点,可保存为 PDF。

获取清单

准备好构建与您业务共同成长的系统了吗?

与 AG·SORA 团队讨论您的需求, 完全免费,无需承诺。