跳转至

数据库迁移规范(Alembic)

本文面向 人类开发者Code Review。Cursor Agent 另见 AGENTS.md.cursor/rules/alembic-migrations.mdc

适用范围

配置 迁移目录
myapp alembic.ini alembic/versions/
backend alembic_backend.ini alembic_backend/versions/

生产 / 共享 PostgreSQL 必须使用 Alembic,禁止依赖启动时 create_all(见 部署指南)。

核心原则

  1. 只升不降:生产环境只执行 upgrade head,禁止 alembic downgrade
  2. 先备份再迁移:ACK / 生产执行前 PostgreSQL 快照或 pg_dump
  3. 先测库后生产:同一 revision 在副本库验证耗时与锁表。
  4. 小步提交:一个 revision 只做一类结构变更,便于回滚应用版本(不是回滚 DB)。
  5. 人工审查 autogenerate:自动生成脚本中的 drop_* / 裸 alter_column 必须删改或拆成多步。

危险操作与替代方案

删列(op.drop_column

阶段 做法
Revision A 应用代码停止读写该列,列仍保留
观察 1~2 个版本 确认无回滚需求
Revision B op.drop_column(此时数据永久丢失)

需保留历史时:归档到别表或重命名为 *_archived,而不是直接 drop。

改列类型(op.alter_column(..., type_=...)

禁止在 upgrade 里直接改类型(易截断/失败)。

推荐四步(可拆两个 revision):

  1. add_column 新列(nullable)
  2. UPDATE 迁移数据(带校验 SQL)
  3. 应用切到新列读写
  4. drop_column 旧列,必要时 rename 新列

PostgreSQL 若必须原地改类型,使用显式 USING 并在副本库验证:

ALTER TABLE t ALTER COLUMN c TYPE integer USING c::integer;

重命名列

使用 op.alter_column(..., new_column_name=...)不要 drop + add(会丢数据)。

删表(op.drop_table

  • upgrade() 中极少使用;若必须,先归档数据并单独评审。
  • downgrade() 中的 drop 仅用于本地/dev 重建,生产禁止 downgrade

执行前检查清单

  • [ ] DATABASE_URL / BACKEND_DATABASE_URL 指向正确环境
  • [ ] 已阅读本次 revision 全部 upgrade() SQL
  • [ ] 无未计划的 drop_column / drop_table / 裸类型变更
  • [ ] 大表变更已评估锁表时间与低峰窗口
  • [ ] 测试库已 upgrade head 通过

命令速查

# 预览 SQL(不真正执行)
poetry run alembic -c alembic_backend.ini upgrade head --sql

# backend 升级
make backend-migrate

# myapp 升级
poetry run alembic upgrade head

# 生成迁移(生成后必须人工改脚本)
poetry run alembic -c alembic_backend.ini revision --autogenerate -m "描述"

相关文档