数据库迁移规范(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(见 部署指南)。
核心原则¶
- 只升不降:生产环境只执行
upgrade head,禁止alembic downgrade。 - 先备份再迁移:ACK / 生产执行前 PostgreSQL 快照或
pg_dump。 - 先测库后生产:同一 revision 在副本库验证耗时与锁表。
- 小步提交:一个 revision 只做一类结构变更,便于回滚应用版本(不是回滚 DB)。
- 人工审查 autogenerate:自动生成脚本中的
drop_*/ 裸alter_column必须删改或拆成多步。
危险操作与替代方案¶
删列(op.drop_column)¶
| 阶段 | 做法 |
|---|---|
| Revision A | 应用代码停止读写该列,列仍保留 |
| 观察 1~2 个版本 | 确认无回滚需求 |
| Revision B | 再 op.drop_column(此时数据永久丢失) |
需保留历史时:归档到别表或重命名为 *_archived,而不是直接 drop。
改列类型(op.alter_column(..., type_=...))¶
禁止在 upgrade 里直接改类型(易截断/失败)。
推荐四步(可拆两个 revision):
add_column新列(nullable)UPDATE迁移数据(带校验 SQL)- 应用切到新列读写
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 "描述"