数据库在线迁移实战:用 Expand-Contract 让新旧版本平滑切换

举报
yd_294777097 发表于 2026/11/02 11:19:59 2026/11/02
【摘要】 本文用扩展、兼容发布、分批回填、读取切换和延后收缩五步,说明如何在新旧应用版本并存时安全演进数据库结构,并给出上线检查清单。

为什么结构变更会影响发布

一次普通的数据库结构变更,可能在发布时变成线上故障:新版本先启动,旧实例仍在处理请求;代码开始读取新列,但回填还没完成;删除旧列后,回滚版本又无法启动。

比较稳妥的做法是把迁移拆成扩展、切换和收缩三段。关键要求是:每次发布期间,新旧应用版本都能使用当前数据库结构。

一、先扩展结构

先增加新列或新表,暂时保留旧结构。新增字段先允许为空,避免数据库立刻扫描并改写所有历史行。对大表创建索引时,选择数据库支持的在线方式,并确认锁等待和执行时间。

例如订单表增加履约状态:

ALTER TABLE orders ADD COLUMN fulfillment_state varchar(24);

不要在同一次变更里添加列、回填数百万行、设置 NOT NULL 并删除旧列。把工作拆开,才能控制锁和回滚范围。

二、发布兼容版本

第一版应用继续能读旧列,同时开始写新列。新旧实例混跑时,两种字段都要保持语义一致。双写会引入短暂的不一致风险,因此要明确写入顺序、失败处理和监控;如果系统已有可靠的变更日志或 CDC,也可以用它同步数据。不要只依赖“部署很快”来假设旧实例不存在。

三、分批回填并验证

按主键范围分批处理,每批提交后记录进度,设置限速,并让任务可以重复执行。更新条件应排除已完成行,这样任务中断后可以安全续跑。观察数据库负载、复制延迟和业务接口的 p95 延迟。

回填完成后,比较新旧字段的空值数量和业务抽样结果。必要时做分批校验,不要在高峰期跑一次全表锁定式更新。

四、切换读取路径

通过配置或功能开关逐步让应用读取新字段。先小流量观察错误率、数据差异和查询耗时,再扩大范围。发现问题时可以把读取切回旧字段;扩展阶段保留的旧列正是回滚缓冲区。

五、最后再收缩

等所有实例都不再依赖旧字段、异步任务和报表也完成切换后,再经过一个观察窗口删除旧列。删除前检查代码搜索结果、慢查询、后台任务和数据导出脚本。收缩是最后一步,不能和新版本发布绑在一起。

上线检查清单

  • 新旧代码都能运行在扩展后的结构上。
  • 回填有批次、进度、限速和重复执行保护。
  • 监控包含锁等待、复制延迟、错误率及接口延迟。
  • 切换读取有开关,回滚时不需要立刻逆向改表。
  • 删除旧结构前,已确认所有消费者都完成迁移。

不同数据库对在线 DDL、索引构建和锁的行为各不相同,执行前要查对应版本的官方文档,并在接近生产的数据量上演练。Expand-Contract 不能消除迁移风险,但它把一次不可逆的大操作拆成多个可观察、可暂停、可回退的小步骤。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。