数据库 Migrations(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/onyx-dot-app/onyx/2.4-database-migrations
翻译时间:2026-05-27T08:44:48.725Z
翻译模型:deepseek-chat
原文字符数:12420
项目:Onyx (onyx)
---
数据库迁移
相关源文件
以下文件被用作生成此 Wiki 页面的上下文:
CONTRIBUTING.mdREADME.mdREADME.zh-CN.mdbackend/alembic.inibackend/alembic/README.mdbackend/alembic/env.pybackend/alembic/versions/351faebd379d_add_curator_fields.pybackend/alembic/versions/57b53544726e_add_document_set_tables.pybackend/alembic/versions/6a804aeb4830_duplicated_no_harm_user_file_migration.pybackend/alembic/versions/6d387b3196c2_basic_auth.pybackend/alembic/versions/800f48024ae9_add_id_to_connectorcredentialpair.pybackend/alembic/versions/9aadf32dfeb4_add_user_files.pybackend/alembic/versions/da4c21c69164_chosen_assistants_changed_to_jsonb.pybackend/alembic_tenants/README.mdbackend/alembic_tenants/env.pybackend/alembic_tenants/script.py.makobackend/alembic_tenants/versions/14a83a331951_create_usertenantmapping_table.pybackend/alembic_tenants/versions/3b45e0018bf1_add_new_available_tenant_table.pybackend/ee/onyx/background/celery/tasks/tenant_provisioning/tasks.pybackend/ee/onyx/server/tenants/schema_management.pybackend/onyx/connectors/README.mdbackend/onyx/db/tag.pybackend/onyx/server/features/build/db/sandbox.pybackend/tests/external_dependency_unit/db/test_tag_race_condition.pybackend/tests/integration/multitenant_tests/tenants/test_tenant_provisioning_rollback.pybackend/tests/integration/tests/indexing/file_connector/test_files/.onyx_metadata.jsonbackend/tests/unit/ee/onyx/server/tenants/test_schema_management.pybackend/tests/unit/onyx/background/celery/tasks/tenant_provisioning/__init__.pybackend/tests/unit/onyx/background/celery/tasks/tenant_provisioning/test_check_available_tenants.pydeployment/README.mddeployment/docker_compose/README.md
目的与范围
本文档介绍了 Onyx 中使用的数据库迁移系统,该系统用于管理 PostgreSQL 数据库的模式演进。内容涵盖 Alembic 迁移框架、迁移文件结构、如何创建和应用迁移,以及基于模式隔离和预置的多租户部署中的特殊注意事项。
有关数据库模式本身和 SQLAlchemy 模型的信息,请参见 8.1 数据库模型与模式。有关多租户架构的详细信息,请参见 9.2 多租户架构。
---
Alembic 迁移系统
Onyx 使用 Alembic(一种轻量级的 SQLAlchemy 数据库迁移工具)来管理随时间变化的模式变更。该迁移系统通过 alembic_version 表实现数据库模式变更的版本控制,并确保在不同安装环境中模式状态可重现。
配置与环境
迁移系统通过 backend/ 目录下的几个关键文件进行配置:
| 文件 | 用途 |
|---|---|
backend/alembic.ini | 主 Alembic 配置文件,包含命名环境如 [alembic] 和 [schema_private]。 |
backend/alembic/env.py | 主(公共)模式的迁移运行时环境。backend/alembic/env.py:1-47 |
backend/alembic_tenants/env.py | 租户特定共享管理模式的迁移运行时环境。backend/alembic_tenants/env.py:1-29 |
backend/alembic/versions/*.py | 包含 upgrade() 和 downgrade() 逻辑的单个迁移脚本。backend/alembic/versions/6d387b3196c2_basic_auth.py:1-20 |
Alembic 使用 alembic_version 表跟踪当前数据库版本,并根据修订 ID 按顺序应用迁移。
迁移存储结构
图示:Alembic 目录组织
graph TB
subgraph "主模式迁移"
AlembicDir["backend/alembic/"]
VersionsDir["backend/alembic/versions/"]
EnvPy["backend/alembic/env.py"]
IniFile["backend/alembic.ini"]
end
subgraph "租户管理迁移"
TenantAlembic["backend/alembic_tenants/"]
TenantEnvPy["backend/alembic_tenants/env.py"]
end
MigrationFiles["迁移脚本 (.py)"]
AlembicDir --> VersionsDir
AlembicDir --> EnvPy
AlembicDir --> IniFile
VersionsDir --> MigrationFiles
EnvPy --> TargetMetadata["target_metadata = [Base.metadata, ResultModelBase.metadata]"]
TenantEnvPy --> TenantMetadata["target_metadata = [PublicBase.metadata]"]
MigrationFiles --> Migration1["6d387b3196c2_basic_auth.py"]
MigrationFiles --> Migration2["351faebd379d_add_curator_fields.py"]
来源: backend/alembic/env.py:47-49, backend/alembic_tenants/env.py:29-30, backend/alembic/versions/6d387b3196c2_basic_auth.py:1-16
---
迁移文件结构
每个迁移文件都遵循标准化的结构,包含修订元数据和用于修改数据库的功能逻辑。
修订元数据
每个迁移文件以标识该迁移并确定其在迁移链中位置的元数据开头。例如,在 Basic Auth 迁移中:
backend/alembic/versions/6d387b3196c2_basic_auth.py:15-18
down_revision 字段创建了一个模式变更的有向无环图(DAG),使 Alembic 能够确定应用迁移的正确顺序。
升级和降级函数
每个迁移实现了两个核心函数:
| 函数 | 用途 | 行为 |
|---|---|---|
upgrade() | 应用模式变更 | 使用 alembic.op 创建表、列或索引。 |
downgrade() | 回滚模式变更 | 撤销 upgrade() 操作以恢复之前的状态。 |
示例:用户表创建 在 6d387b3196c2_basic_auth.py 迁移中,upgrade() 函数使用 op.create_table 创建 user 表:
backend/alembic/versions/6d387b3196c2_basic_auth.py:21-37
对应的 downgrade() 函数会删除该表:
backend/alembic/versions/6d387b3196c2_basic_auth.py:92-93
---
多租户迁移管理
Onyx 支持多租户架构,通过 PostgreSQL 模式实现数据隔离。这需要一种专门的迁移策略,在 backend/alembic/env.py 中管理,并通过 run_alembic_migrations 以编程方式执行。
模式管理逻辑
当启用 MULTI_TENANT 时,迁移会针对特定的租户模式运行。系统使用严格的正则表达式校验来防止模式操作期间的 SQL 注入。
关键多租户函数:
run_alembic_migrations(schema_name):以编程方式对特定模式执行 Alembicupgrade head。backend/ee/onyx/server/tenants/schema_management.py:39-75validate_tenant_id(tenant_id):在将租户 ID 格式化为 SQL 之前,确保其符合 UUID 或 AWS 实例 ID 格式。backend/ee/onyx/server/tenants/schema_management.py:30-36filter_tenants_by_range():通过将租户列表拆分为范围来实现迁移并行化。backend/alembic/env.py:59-105get_schema_options():解析 CLI 参数(通过-x传递)以控制迁移行为(例如upgrade_all_tenants=true)。backend/alembic/env.py:108-180
租户预置与维护
在云/多租户部署中,后台任务 check_available_tenants 确保存在一个随时可用的租户池。
图示:租户预置与迁移流程
graph TD
subgraph "后台任务:check_available_tenants"
Start["Celery 任务"] --> CheckPool["检查 AvailableTenant 数量"]
CheckPool --> NeedMore{"低于目标?"}
NeedMore -- 是 --> PreProv["pre_provision_tenant()"]
PreProv --> CreateSchema["create_schema_if_not_exists()"]
CreateSchema --> RunMigrate["run_alembic_migrations(tenant_id)"]
RunMigrate --> SetupTenant["setup_tenant()"]
SetupTenant --> Success["添加到 AvailableTenant 表"]
NeedMore -- 否 --> MigrateStale["_migrate_stale_pool_tenants()"]
MigrateStale --> ForEachPool["遍历每个池租户"]
ForEachPool --> RunMigratePool["run_alembic_migrations(tenant_id)"]
end
来源: backend/ee/onyx/background/celery/tasks/tenant_provisioning/tasks.py:39-114, backend/ee/onyx/background/celery/tasks/tenant_provisioning/tasks.py:127-165, backend/ee/onyx/server/tenants/schema_management.py:39-75
---
部署场景
迁移已集成到 Onyx 的生命周期中,以确保数据库始终与代码保持同步。
执行命令
| 场景 | 命令 | 上下文 |
|---|---|---|
| 标准生产环境 | alembic upgrade head | 在启动 FastAPI 应用之前,在 api_server 容器中执行。 |
| 多租户(全部) | alembic -x upgrade_all_tenants=true upgrade head | 按顺序升级每个租户模式。backend/alembic/README.md:32-35 |
| 特定模式 | alembic -x schemas=tenant_123,public upgrade head | 仅升级指定的模式。backend/alembic/README.md:37-44 |
| 租户范围 | alembic -x upgrade_all_tenants=true -x tenant_range_start=100 -x tenant_range_end=200 upgrade head | 用于并行化迁移。backend/alembic/README.md:46-56 |
迁移完整性与回滚
系统包含针对失败迁移的健壮错误处理:
- 编程式回滚: 如果
pre_provision_tenant在模式创建后失败,会调用drop_schema清理孤立的模式。backend/tests/integration/multitenant_tests/tenants/test_tenant_provisioning_rollback.py:38-46 - 幂等性:
run_alembic_migrations可以安全地重复执行;如果模式已经处于head状态,则快速执行无操作(no-op)。backend/ee/onyx/background/celery/tasks/tenant_provisioning/tasks.py:127-132
工作流总结
图示:代码实体空间到迁移空间
graph LR
subgraph "代码实体空间"
Model["User (onyx/db/models.py)"]
Token["AccessToken (onyx/db/models.py)"]
end
subgraph "迁移空间"
Rev["6d387b3196c2_basic_auth.py"]
Op1["op.create_table('user')"]
Op2["op.create_table('accesstoken')"]
end
Model -- "定义模式" --> Rev
Token -- "定义模式" --> Rev
Rev -- "实现" --> Op1
Rev -- "实现" --> Op2
Op1 -- "SQL 执行" --> DB["PostgreSQL 表:user"]
Op2 -- "SQL 执行" --> DB2["PostgreSQL 表:accesstoken"]
来源: backend/alembic/versions/6d387b3196c2_basic_auth.py:21-54, backend/ee/onyx/server/tenants/schema_management.py:39-75, backend/ee/onyx/background/celery/tasks/tenant_provisioning/tasks.py:127-165