梳理每个读取方和写入方
在隔离的模式和具有代表性的脱敏数据上开展工作。你需要当前和下一版应用、对迁移框架的了解、经过评审的备份策略,以及对长事务的可见性。要纳入工作进程、计划任务、报表和较旧的应用实例。API 可能更新很快,而长时间运行的工作进程仍在写入旧列。
我们的示例报表服务将导出标签存储在 label 并希望使用 display_name。这是一个设计示例,不是通用的可运行 SQL。在选择迁移语法或锁设置之前,请确认你确切的 PostgreSQL 版本和框架。
在不弃用旧表示的前提下进行扩展
首先引入新的可空字段。部署一个兼容性版本,在一个事务中同时写入两个值,并在数据不完整时按所需的回退逻辑读取。定义当客户在回填期间编辑记录时会发生什么。重试不得创建第二个逻辑导出。
PostgreSQL ALTER TABLE 操作会获取锁,锁的级别取决于子命令。一个小变更可能排在长事务后面等待,然后阻碍其他工作。在演练期间审查具体操作并观察等待情况;增量式并不意味着无锁。
技术参考: PostgreSQL ALTER TABLE · PostgreSQL 显式锁定.
让兼容性边界清晰可见
| 模式与写入方 | 读取方行为 | 恢复决策 |
|---|---|---|
| 仅存在 label | 支持旧代码 | 先添加新字段 |
| 两个字段;仅写旧字段的写入方仍然存在 | 将 label 作为权威读取 | 暂不切换读取方 |
| 所有写入方双写;已验证回填 | 新字段可以成为权威 | 仅回滚到兼容的双写代码 |
| 旧字段已删除 | 任何代码都不得引用 label | 旧产物不兼容 |
针对缺失值的回退无法检测非空但过时的新值。在切换读取方之前,先弃用仅写旧字段的写入方并验证一致性。在读取方切换后回滚到仅写旧字段的代码,可能会重新产生分歧。请保留兼容性版本作为经过评审的恢复产物。
以有界、可重启的工作进行回填
找到需要复制的行,同时不覆盖较新的客户编辑。使用稳定的排序、并发安全的更新条件和根据工作负载选择的批次大小。持久化进度,以便失败时可以在已知边界处恢复。监控写入量、锁等待、请求延迟以及存在时的复制情况。
没有一种批次大小对所有应用都安全。在演练中,将小批量与正常流量进行比较,然后选择暂停或停止规则。如果某个批次失败,在重试之前检查已提交的内容。无限重试循环可能将可恢复的不匹配变成持续的数据库压力。
检查语义,而不仅是已填充的行
验证缺失值、具有代表性的标签、新记录以及对现有导出的更新。统计非空行可能看起来正确,而值却是从错误的来源复制的。针对部分填充的数据测试兼容性产物,并演练在部署前启动的工作进程。
记录模式版本、迁移修订版、完成标准和互不兼容的组合。在删除任一项之前,先检查回退使用情况和一致性。如果检查失败,停止回填或推进,保留证据,并选择兼容的产物或经过评审的前向修复。不要声称应用回滚可以重建已提交的数据。
在另一次经过评审的发布中弃用旧字段
当回填和观察期满足你的标准后,移除旧的读取和写入。除交互式路由外,也要检查不频繁的任务。删除旧字段应属于后续变更,并有其自身的恢复决策,这样发布问题就不会迫使你将代码修复与数据重建合并在一起。
如果弃用后出现坏数据,停止进一步损害,并使用恢复计划或经批准的修复。不要仅仅因为工具提供了回滚按钮就执行破坏性的向下迁移。将矩阵附加到 发布记录 并演练 数据恢复 然后再更改生产环境。有用的结果是明确的兼容性边界,而不是零停机保证。
官方参考
本文档已针对本文进行审核。示例是规划练习,不是已在 PrivacyNodes 服务器上测试过的命令。请查阅你所安装版本的文档。