用途:为 Saleor 编写安全的 Django 迁移。Saleor 在多 Pod 共享 Postgres 上零停机部署,任何长时间表锁都会拖住所有 Pod,因此迁移需遵循以下规则。
主要能力与规则:
- 缩短锁时间:一个迁移只改一个模型、一个字段;每个 schema 操作都会在持续期间锁表,批量合并会成倍增加锁时间。唯一可合并的理由是把 schema 迁移与数据迁移分开。始终分离 schema 变更与数据迁移。不要新增重复修改已有迁移改过的列的迁移,先检查迁移历史。迁移命名要描述实际操作(如 0070_add_payment_gift_card_brand)。
- 索引与约束并发创建:用既有的非阻塞模式并发添加唯一约束/索引(参考 page 迁移 0030_slug_translation_unique_constraint);普通 AddConstraint/AddIndex 会取阻塞的 ACCESS EXCLUSIVE 锁。值不变量(如余额非负)用 DB CheckConstraint 强制,而非仅靠应用逻辑。
- 删除字段要分阶段:一步删除 NOT NULL/带默认值的列会在新旧 Pod 共存时失败。分多次发布:先加 db_default 让 DB 无需 ORM 即可写列;再从 ORM 模型移除字段(列仍在);后续版本再删列,并用显式跟进 issue 跟踪。仅为迁移安全保留的旧枚举值/代码,需以“remove in X.Y”备注跟踪。
- 数据迁移:必须全有或全无,不能按固定深度/数量上限中途退出留下部分迁移。post_migrate 的 sender 必须是该迁移自己的 app config(常见复制粘贴错误是在 account/order 迁移里写 registry.get_app_config("product"))。内部调参用模块/任务常量(如 BATCH_SIZE),不要用没人会设的环境变量。清理(如移除权限)时要覆盖所有持有该值的模型(App、AppExtension、AppInstallation 等),否则说明为何在别处处理。注意每次迭代的 DB 查询(O(N) vs O(1)),批量处理相关查询。
- 跨分支移植:移植迁移的文件名要与另一分支对应文件一致,历史分叉处用 ./manage.py makemigrations --merge 添加合并迁移。
使用方式与检查:提交评审前确认每个迁移只涉及单模型单字段,索引/约束为并发创建;破坏性列变更已跨版本分阶段;每个 post_migrate 处理器以自身 app config 为 sender,数据迁移全有或全无;本地运行 manage.py migrate 确认可干净应用。
限制:资料未提供具体版本号、性能数据或额外工具支持。