Files
life-echo/api/docs/alembic-migrations.md

60 lines
2.5 KiB
Markdown
Raw Normal View History

2026-05-19 16:40:45 +08:00
# Alembic 迁移规范
## 设计原则
1. **`0001` 仅服务全新库**`create_all` 不会对已有表 `ALTER`。老库缺列必须用 **`0019` 及之后的显式迁移** 补齐。
2. **一条迁移 = 明确 DDL**:禁止用「全库 ORM 内省」替代清单;可审查、可测、各环境行为一致。
3. **已部署的 `revision` 永不改名**:文件名可描述用途,但 `revision = "..."` 一旦上线不得修改。
4. **新 ORM 字段同 PR 必须带迁移**:改 `models.py` 须同时 `alembic/versions/` 新增或扩展迁移(见 CI 测试)。
## 当前链
```
0001_initial → … → 0018_users_language_preference → 0019_align_legacy_schema (head)
```
`0019_align_legacy_schema` 维护「老库相对 0001 squash 常缺」的列清单,见 `alembic/versions/0019_align_legacy_schema.py``_LEGACY_COLUMNS`
## 新增字段流程
1. 修改 ORM `models.py`
2. 若表在 squash 前就存在且 00020018 未覆盖该列 → 在 `0019``_LEGACY_COLUMNS` 追加一行(未部署前),或新建 `0020_<short_desc>.py`
3. 本地:`uv run alembic upgrade head`
4. 提交前:`uv run pytest tests/test_alembic_migration_policy.py`
## Staging / Production 发布
| 环境 | 代码来源 | 说明 |
|------|----------|------|
| Staging | `main` push | 迁移在容器启动时 `upgrade head` |
| Production | tag `v*.*.*` | 发 tag 前确认 staging 已成功跑过同一迁移链 |
生产推荐:`ALEMBIC_STARTUP_FAIL_FAST=true`,迁移失败则进程退出。
## 撤回错误迁移 0019/0020 后的库修复
若数据库 `alembic_version` 仍为已删除的 revision例如 `0020_add_tts_audio_urls_column``0020_backfill_missing_schema`**部署新代码前**先执行:
```bash
cd api
# 仅当 version_num 为已撤回的 0020_* 时
uv run python scripts/repair_alembic_version_after_withdrawn_0020.py
```
或手动 SQL确认列已由旧迁移加过后再 stamp
```sql
SELECT version_num FROM alembic_version;
-- 若为 0020_add_tts_audio_urls_column 或 0020_backfill_missing_schema
UPDATE alembic_version SET version_num = '0018_users_language_preference';
```
然后部署;`0019_align_legacy_schema` 会幂等补齐缺列。
## 禁止事项
- 修改已上线 migration 的 `revision` / `down_revision`
-`0020_backfill_*` 式全表内省替代显式列清单
- 只在 ORM 加字段、指望 `create_all` 更新线上老库
- Staging 与 Production 长期使用不同迁移链(应同一 commit / 同一 tag 构建)