# Alembic 迁移系统实施 **日期**: 2026-01-27 **类型**: 基础设施改进 **影响范围**: 数据库迁移工具 ## 概述 将项目的数据库迁移系统从自定义脚本迁移到 Alembic,提供更强大的版本管理、自动生成和回滚功能。 ## 变更内容 ### 1. 新增文件 #### 配置文件 - `server/alembic.ini` - Alembic 主配置文件 - `server/alembic/env.py` - 环境配置,支持异步数据库 - `server/alembic/script.py.mako` - 迁移文件模板 - `server/alembic/versions/.gitkeep` - 版本目录占位 #### 工具脚本 - `server/scripts/db_migrate.py` - 便捷迁移命令封装 #### 文档 - `docs/server/guides/alembic-migration-guide.md` - 完整使用指南 ### 2. 修改文件 #### 迁移脚本 - `server/migrate_db.sh` - 更新为使用 Alembic #### 技术栈文档 - `.claude/skills/jointo-tech-stack/references/database.md` - 更新迁移管理部分 ### 3. 保留文件 - `server/app/migrations/` - 旧迁移文件保留作为参考 - `server/run_migration.py` - 保留但标记为 deprecated ## 功能特性 ### 1. 自动生成迁移 ```bash # 自动检测模型变更并生成迁移脚本 python scripts/db_migrate.py create "描述" --autogenerate ``` ### 2. 版本管理 - 基于 Git 风格的版本链 - 支持分支合并 - 自动依赖管理 ### 3. 回滚支持 ```bash # 回滚一个版本 python scripts/db_migrate.py downgrade # 回滚到指定版本 python scripts/db_migrate.py downgrade <版本号> # 回滚所有 python scripts/db_migrate.py downgrade base ``` ### 4. 状态查询 ```bash # 当前版本 python scripts/db_migrate.py current # 迁移历史 python scripts/db_migrate.py history # 最新版本 python scripts/db_migrate.py heads ``` ## 技术实现 ### 1. 异步支持 `alembic/env.py` 配置了异步数据库引擎: ```python async def run_async_migrations() -> None: """在线模式运行异步迁移""" connectable = engine async with connectable.connect() as connection: await connection.run_sync(do_run_migrations) await connectable.dispose() ``` ### 2. 模型导入 自动导入所有 SQLModel 模型以支持 autogenerate: ```python from app.models.user import User, UserSession from app.models.folder import Folder from app.models.project import Project, ProjectMember from app.models.credit import CreditTransaction, CreditConsumptionLog # ... 更多模型 ``` ### 3. Jointo 规范集成 #### 禁止外键约束 ```python def render_item(type_, obj, autogen_context): """自定义渲染逻辑""" # 禁止自动生成外键约束(Jointo 规范) if type_ == "foreign_key": return False return False ``` #### 过滤对象 ```python def include_object(object, name, type_, reflected, compare_to): """过滤要包含的数据库对象""" # 忽略 Alembic 自己的版本表 if type_ == "table" and name == "alembic_version": return False # 忽略旧的迁移记录表 if type_ == "table" and name == "schema_migrations": return False return True ``` ### 4. 便捷脚本 `scripts/db_migrate.py` 提供友好的命令行界面: - 彩色输出 - 详细帮助信息 - 安全确认(回滚操作) - 错误处理 ## 使用示例 ### 创建新迁移 ```bash # 1. 修改模型 # server/app/models/user.py class User(SQLModel, table=True): user_id: UUID = Field(default_factory=uuid7, primary_key=True) username: str = Field(max_length=255, unique=True) phone: Optional[str] = Field(default=None, max_length=20) # 新增 # 2. 生成迁移 python scripts/db_migrate.py create "添加用户手机号字段" --autogenerate # 3. 检查生成的文件 # server/alembic/versions/20260127_1430_abc123_添加用户手机号字段.py # 4. 执行迁移 python scripts/db_migrate.py upgrade ``` ### 回滚迁移 ```bash # 回滚一个版本 python scripts/db_migrate.py downgrade # 确认提示 # 警告:此操作可能导致数据丢失 # 确认继续?(yes/no): yes ``` ### 查看状态 ```bash # 当前版本 $ python scripts/db_migrate.py current INFO [alembic.runtime.migration] Context impl PostgresqlImpl. INFO [alembic.runtime.migration] Will assume transactional DDL. Current revision for postgresql://...: abc123 (head) # 迁移历史 $ python scripts/db_migrate.py history abc123 -> xyz789 (head), 添加用户手机号字段 xyz789 -> def456, 创建项目表 def456 -> , 初始迁移 ``` ## 迁移路径 ### 从旧系统迁移 如果数据库已使用旧迁移系统: ```bash # 1. 创建基线迁移 python scripts/db_migrate.py create "baseline" --autogenerate # 2. 标记为已应用(不执行) python scripts/db_migrate.py stamp head # 3. 验证 python scripts/db_migrate.py current ``` ### 新项目 直接使用 Alembic: ```bash # 1. 创建初始迁移 python scripts/db_migrate.py create "initial" --autogenerate # 2. 执行迁移 python scripts/db_migrate.py upgrade ``` ## 最佳实践 ### 1. 开发流程 1. 修改模型 2. 生成迁移:`create "描述" --autogenerate` 3. 检查生成的代码 4. 测试 upgrade 和 downgrade 5. 提交代码 ### 2. 命名规范 - 使用动词开头:`添加`、`修改`、`删除` - 包含表名和字段名 - 清晰明确 ### 3. 代码审查 - 检查是否符合 Jointo 规范 - 验证 downgrade 逻辑 - 确认数据迁移安全 ### 4. 生产部署 ```bash # 1. 备份数据库 pg_dump -U postgres jointo > backup.sql # 2. 执行迁移 python scripts/db_migrate.py upgrade # 3. 验证 python scripts/db_migrate.py current ``` ## 优势对比 | 功能 | 旧系统 | Alembic | |------|--------|---------| | 自动生成 | ❌ | ✅ | | 版本管理 | ⚠️ 手动 | ✅ 自动 | | 回滚支持 | ⚠️ 不完整 | ✅ 完整 | | 模型同步检测 | ❌ | ✅ | | 分支合并 | ❌ | ✅ | | 依赖管理 | ❌ | ✅ | | 状态查询 | ⚠️ 基础 | ✅ 详细 | | 社区支持 | ❌ | ✅ | ## 注意事项 ### 1. 外键约束 Alembic 默认会生成外键约束,但 Jointo 规范禁止使用。已在 `env.py` 中配置自动过滤: ```python def render_item(type_, obj, autogen_context): if type_ == "foreign_key": return False # 禁止生成外键 return False ``` ### 2. 枚举类型 使用 SMALLINT 而非 PostgreSQL ENUM: ```python # ✅ 正确 sa.Column('status', sa.SmallInteger(), nullable=False) # ❌ 错误 sa.Column('status', sa.Enum('active', 'archived', name='status'), nullable=False) ``` ### 3. UUID v7 确保使用 UUID v7 函数: ```python sa.Column('id', sa.UUID(), server_default=sa.text('gen_uuid_v7()'), nullable=False) ``` ### 4. 时间戳 使用 TIMESTAMPTZ 和触发器: ```python sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False) sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False) ``` ## 后续计划 ### 短期 - [ ] 创建基线迁移标记当前数据库状态 - [ ] 归档旧迁移文件到 `.archive/` - [ ] 更新部署文档 ### 中期 - [ ] 添加迁移测试自动化 - [ ] 集成到 CI/CD 流程 - [ ] 添加迁移性能监控 ### 长期 - [ ] 探索零停机迁移策略 - [ ] 实现迁移回滚自动化 - [ ] 建立迁移最佳实践库 ## 参考资料 - [Alembic 官方文档](https://alembic.sqlalchemy.org/) - [SQLAlchemy 文档](https://docs.sqlalchemy.org/) - [Alembic 迁移指南](../guides/alembic-migration-guide.md) - [Jointo 数据库规范](../../.claude/skills/jointo-tech-stack/references/database.md) ## 相关文档 - [RFC 136: Alembic 迁移系统设计](../rfcs/136-alembic-migration-system.md) - [数据库设计规范](../../requirements/database-design.md) - [部署指南](../DEPLOYMENT.md)