本文由 AI 辅助整理,技术边界依据文末官方文档核对。下面的网站与发布版本均为假设,用于说明判断方法,不代表生产实测或客户案例。
本文首发于知乎:zhuanlan.zhihu.com/p/209493159... ,此处同步整理。
假设一个小团队维护预约网站:应用用 Docker Compose 部署,PostgreSQL 保存预约数据。新版上线后,提交表单频繁报错,团队准备切回昨天的镜像。
此时最关键的问题是:昨天的程序,能否正确读写今天的数据库?
一、镜像退回去了,数据未必回去
Compose 的 up 会在服务配置或镜像变化时重建容器,并保留挂载卷。1 这意味着切回应用镜像通常仍会连接已经执行迁移的数据库;它不会替你撤销表结构修改,也不会把上线后的业务写入恢复成旧状态。
假设新版把预约表的 email 改名为 contact_email,旧代码仍查询 email。即使旧容器成功启动,提交预约也可能继续失败。反过来,即便字段都在,新版写入了旧代码不认识的状态值,旧程序也可能读错或覆盖数据。
因此,回退依据不能只有"容器健康":至少要核对旧程序所需字段、约束、数据含义及写入路径。
还要检查旧镜像的启动入口:它是否会自动执行迁移,是否依赖已经变更的环境变量。恢复旧代码之前,应把这些启动副作用一并列入回退方案。
二、先看这次迁移越过了哪条边界
可以把迁移清单逐条归入三类:
增加结构:新增可空字段,且旧代码显式列出读写字段,通常更容易兼容;仍要检查 ORM 映射和新增约束,不能把"只增加"直接等同于安全。
改变契约:重命名字段、改变字段类型、增加非空要求,都可能使旧查询或旧写入失效。PostgreSQL 的 ALTER TABLE 不同操作还有不同锁定行为;兼容性和执行期间的阻塞是两项检查。2
破坏数据:删除字段、删表、清空或不可逆地转换数据。重新建一个同名字段不会把原值变回来。Flyway 的 Undo 文档也明确区分结构撤销与数据恢复的限制。3
还要核实迁移实际执行到了哪里。脚本文件存在、流水线显示失败,都不能单独证明数据库处于哪个版本。迁移失败后先读执行记录和实际结构,不按"整批一定成功"或"整批一定撤销"继续操作。
三、把字段替换拆成可回退的阶段
对于前面的字段替换,可以采用扩展---收缩思路:先保留旧接口,再迁移使用方式,最后删除旧结构。4 以下顺序是一种设计示例,并非通用迁移脚本。
第一步,只增加可空的 contact_email,保留 email。此时旧应用继续按原方式运行。
第二步,发布过渡版本:仍读 email,但所有相关写入同时维护两个字段。同库双写应放入同一事务;后台任务、导入脚本和管理工具也要纳入检查。只改网页接口,不能证明双写完整。
第三步,回填历史数据并核对一致性。回填任务需要考虑并发修改,避免用较旧的值覆盖刚提交的数据;执行时长、分批方式和中断后的续跑规则应先在隔离环境验证。
第四步,发布改读 contact_email 的版本,同时继续维护 email。此阶段的回退目标应是已经双写的过渡版本,而非任意一个更旧镜像。否则回退期间的新写入可能只更新旧字段,再次前进时读到过期的新字段。
第五步,确认所有读写者已迁移、回退窗口结束,再单独安排删除 email。删除后,依赖它的镜像就应退出可回退列表。
扩展和收缩不要塞进同一次发布。额外字段能留下选择空间,但只有同步规则和兼容验证成立,空间才真正可用。
四、遇到这些情况,先停止切镜像
如果旧代码所需字段已删除、两份数据无法一致对应、迁移只执行了一部分,或新写入无法用旧业务规则解释,就不应继续盲目回退。
先按既定预案限制受影响的写入,保留当前数据和执行日志,再比较向前修复、兼容补丁或从备份恢复的代价。恢复到较早时间点还要处理这段时间内的合法新增数据;"有备份"并不代表可以直接覆盖当前数据库。
五、每次发布留下最小记录
不必先做复杂平台,一张发布记录至少写清:
- 当前与回退目标的镜像摘要、配置版本;
- 迁移编号、实际执行结果,以及数据库结构状态;
- 允许回退的版本和有效窗口,哪些变化会关闭窗口;
- 旧版在新结构上的读写验证结果,包含一条关键业务流程;
- 停止条件、负责人、备份位置及最近一次恢复验证时间。
这张记录要能回答一个具体问题:如果现在退回目标版本,已经写入的预约会怎样,下一笔预约又会怎样?答不清楚时,旧镜像只是一个文件,还不是可用的恢复方案。
官方资料(核验于 2026-10-17)
1 Docker Compose up:容器重建与挂载卷保留 docs.docker.com/reference/c...
2 PostgreSQL 18 ALTER TABLE:结构变更与锁定语义 www.postgresql.org/docs/18/sql...
3 Flyway Undo migrations:撤销迁移的限制 documentation.red-gate.com/flyway/flyw...
4 Flyway 批量部署指南:Backward-compatible changes(expand/contract) documentation.red-gate.com/flyway/depl...