尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

LiteLLM Proxy 数据库迁移实战:schema.prisma 三份副本同步、prisma migrate diff 生成迁移与双重安全护栏

LiteLLM Proxy 数据库迁移实战:schema.prisma 三份副本同步、prisma migrate diff 生成迁移与双重安全护栏 LiteLLM Proxy 数据库迁移实战schema.prisma 三份副本同步、prisma migrate diff 生成迁移与双重安全护栏【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100 LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm本篇技术文章以 migration_runbook.md 这份官方迁移运维手册Runbook为主体完整覆盖从三份schema.prisma文件同步、ci_cd/run_migration.py生成迁移 SQL到分支新鲜度检查与破坏性 DDL 护栏的全部操作细节并结合 run_migration.py 源码与 migrations/run.py 运行时入口讲解每一步命令背后的底层实现。读完后你将能够在本地安全地生成一个 Prisma 迁移、正确应对STALE BRANCH与DESTRUCTIVE MIGRATION DETECTED两类拒绝信号并理解生成的迁移如何在生产容器内被prisma migrate deploy应用。背景迁移文件为什么住在 litellm-proxy-extras 独立包里LiteLLM Proxy 的数据库层基于 Prismadatasource指向 PostgreSQL见 schema.prisma 头部声明当前主 schema 约 1600 行定义预算、密钥、Team、MCP Server、向量存储等全部代理侧数据模型。为了控制主包litellm的安装体积迁移历史被拆分到独立发布的 PyPI 包litellm-proxy-extras中其 pyproject.toml 明确写着 Reduces the size of the main litellm package当前版本 0.4.93通过 commitizen 管理并同时联动根目录pyproject.toml中的版本 pin。因此这份 runbook 的核心动作是修改根schema.prisma→ 同步三份副本 → 用临时数据库对比差异 → 把新生成的迁移 SQL 落到litellm-proxy-extras/litellm_proxy_extras/migrations/。截至当前仓库该目录下已有 160 余个按时间戳命名的迁移如20250326162113_baseline、20260901000000_shadow_eval_multi_router以及一个声明provider postgresql的 migration_lock.toml。runbook 开篇即注明 For use for litellm engineers only且专门给 AI Agent 立下规矩当脚本以STALE BRANCH或DESTRUCTIVE MIGRATION DETECTED拒绝时禁止自行git rebase、传--skip-freshness-check或--allow-destructive必须把错误交给人类操作者确认。这一点在后文两处护栏章节会再强调。Step 0同步全部三份 schema.prisma不可跳过仓库中有三处schema.prisma副本必须保持一致否则生成的迁移可能凭空DROP掉其他副本中已存在的列文件用途schema.prisma仓库根目录唯一事实来源Source of truthlitellm/proxy/schema.prisma供 proxy 服务器运行时使用litellm-proxy-extras/litellm_proxy_extras/schema.prisma供迁移生成使用runbook 给出的同步流程是# 1. Diff all schema files against the root source of truth diff schema.prisma litellm/proxy/schema.prisma diff schema.prisma litellm-proxy-extras/litellm_proxy_extras/schema.prisma # 2. If there are differences, copy the root schema to all locations cp schema.prisma litellm/proxy/schema.prisma cp schema.prisma litellm-proxy-extras/litellm_proxy_extras/schema.prisma # 3. Verify all files are now identical diff schema.prisma litellm/proxy/schema.prisma echo proxy schema in sync || echo MISMATCH diff schema.prisma litellm-proxy-extras/litellm_proxy_extras/schema.prisma echo extras schema in sync || echo MISMATCH在所有 schema 文件完全一致之前不要进入迁移生成步骤。runbook 原文警告我们在当前仓库上实际执行了第 1、3 步的diff -q三份副本目前完全一致——也就是说仓库维护者正在严格执行这套规则。这也解释了为什么 run_migration.py 生成 diff 时只读取根目录的schema.prisma它假设副本已经与事实来源对齐。Step 1快速上手——生成一条迁移环境准备与生成命令来自 runbook 原文可直接复制# Install deps for this command uv sync --frozen --all-groups --all-extras brew install postgresql14 # macOS # Add to PATH export PATH/opt/homebrew/opt/postgresql14/bin:$PATH # Run migration uv run --with testing.postgresql python ci_cd/run_migration.py your_migration_name命令拆解uv sync --frozen --all-groups --all-extras按锁文件安装全部依赖组保证本地环境与 CI 一致testing.postgresql是临时依赖--with注入它会拉起一个本地一次性 PostgreSQL 实例脚本用它重放全部已有迁移得到基准库状态——全程不碰任何真实数据库postgresql14提供initdb/postgres可执行文件testing.postgresql需要它们在PATH中migration_name会被拼进生成目录名runbook 要求使用描述性名称。它到底做了什么run_migration.py 的六步流程与源码印证runbook 概述了 6 步行为对照 create_migration() 的源码完整链路如下分支新鲜度校验见下节——HEAD落后于基线分支则直接退出exit code 3testing.postgresql.Postgresql()创建临时 PostgreSQL 数据库并把DATABASE_URL指向它源码 L235-L236把litellm-proxy-extras/litellm_proxy_extras/migrations/整个复制到根schema.prisma旁的临时migrations/目录然后执行prisma migrate deploy --schema schema.prisma将已有迁移全部重放到临时库执行prisma migrate diff --from-url 临时库 --to-schema-datamodel schema.prisma --script对比重放完历史后的库与当前 schema得到增量 SQL若 diff 为空Prisma 会输出字面量-- This is an empty migration.脚本对两种空形态都做了识别见 L273-L277则打印 No schema changes detected. Migration not needed. 并返回 False否则检查 diff 中是否含破坏性语句见下节通过后按%Y%m%d%H%M%S时间戳创建目录migrations/{timestamp}_{migration_name}/把 SQL 写入其中的migration.sql。finally块会清理临时migrations/目录保证失败路径不留垃圾。所有 Prisma 子进程调用都以checkTrue运行任何一步失败都会打印 stderr 并返回 False。护栏一分支新鲜度检查STALE BRANCH生成任何内容之前脚本先执行git fetch origin base再用git rev-list --count HEAD..origin/base计算落后提交数源码 _check_branch_freshness。默认基线分支是litellm_internal_staging——PR 的目标分支DEFAULT_BASE_BRANCHL14。为什么如此严格runbook 明确记录了事故背景A previous incident saw a stale branch silently drop production columns——一次事故中落后分支在生成 diff 时把别的分支新增的列当成需要删除的漂移产出了DROP COLUMN并混入主分支。新鲜度检查就是第一道防线。相关标志位--base-branch name— 改用其他基线分支检查如main默认litellm_internal_staging--skip-freshness-check— 完全跳过仅限有意针对旧基线生成迁移的场景。护栏触发退出码 3后的处理步骤git fetch origin git rebase origin/litellm_internal_staging # or git merge origin/litellm_internal_staging — whichever matches your workflow然后重新运行run_migration.py。注意git fetch本身失败无网络、origin未配置、不是 git 仓库同样会以退出码 3 拒绝并打印常见原因清单。AI AGENTS / ASSISTANTS不要自动 rebase、不要自动传--skip-freshness-check。rebase 中一次糟糕的冲突解决本身就可能丢掉人类正在编辑的 schema 改动。把错误呈现给操作者等待其明确确认runbook 与脚本输出中均有此警告见 L87-L93。护栏二破坏性迁移拦截DESTRUCTIVE MIGRATION DETECTED生成的 SQL 若包含DROP COLUMN、DROP TABLE或DROP INDEX脚本拒绝写入迁移文件并以非零退出退出码 2。匹配逻辑是一个简单的行级正则DESTRUCTIVE_PATTERN re.compile(r\bDROP\s(COLUMN|TABLE|INDEX)\b, re.IGNORECASE)L13触发后_print_destructive_refusal 会逐行打印每一条被拦截的DROP语句并提示这通常意味着你的分支过期了或本地schema.prisma与migrations/目录不一致。人工处置四步runbook 原文git fetch origin git status—— 确认分支与基线同步重跑 Step 0确认三份schema.prisma一致逐条审查错误中打印的每个DROP语句——它是否真的被有意删除仅当确认删除是有意行为时带旗标重跑uv run --with testing.postgresql python ci_cd/run_migration.py your_migration_name --allow-destructive此时脚本仍会把所有破坏性语句打印出来WARNING: writing destructive migration只是允许落盘。AI AGENTS / ASSISTANTS不要自动带--allow-destructive重跑。未经人工审查就传这个旗标正是该护栏要阻止的失败模式runbook 与脚本输出双重强调。常见故障修复Common Fixesrunbook 汇总了三类高频问题以下命令在你的本地工作副本中执行缺少 testing 模块—— 不要单独pip install直接用--with注入uv run --with testing.postgresql python ci_cd/run_migration.py your_migration_name找不到initdbmacOS Homebrew 的 keg-only 问题brew install postgresql14 export PATH/opt/homebrew/opt/postgresql14/bin:$PATH空迁移目录报错—— 上一次中断可能留下空目录删除对应目录即可注意替换方括号为实际目录名rm -rf litellm-proxy-extras/litellm_proxy_extras/migrations/[empty_dir]迁移纪律Rules 清单runbook 以 6 条硬性规则收尾适合作为团队 checklist先同步全部schema.prismaStep 0先改仓库根目录的schema.prisma再同步副本提交前逐行审查生成的 SQL使用描述性迁移名永远不要编辑已有的迁移文件迁移历史只增不改migrations/下的 SQL 是不可变历史schema 与迁移必须一起提交。延伸生成的迁移如何在运行时被应用理解这一节可以完整闭环生成 → 发布 → 生效链路。迁移文件随litellm-proxy-extras包发布后生产的迁移 Job 容器由 migrations/run.py 驱动它通过ProxyExtrasDBManager.setup_database定义在 litellm-proxy-extras/litellm_proxy_extras/utils.py对写库执行prisma migrate deploy默认使用v2 解析器USE_V2_MIGRATION_RESOLVERtrue内置 P3005空库基线、P3009/P3018幂等错误恢复逻辑、对并发migrate deploy的死锁/咨询锁重试最多 4 次DATABASE_URL可由离散DATABASE_*环境变量组装或在IAM_TOKEN_DB_AUTHtrue时从 IAM token 铸造USE_PRISMA_DB_PUSHtrue可改用prisma db pushmigrations/Dockerfile 构建了一个刻意精简的镜像跳过 gateway/backend 的重型 extras在构建期就完成prisma generate预热二进制缓存运行期以PRISMA_OFFLINE_MODEtrue工作Pod 启动时不再触网各 Prisma 命令的超时预算可由环境变量覆盖默认值为普通命令LITELLM_PRISMA_COMMAND_TIMEOUT60s、工具链引导LITELLM_PRISMA_BOOTSTRAP_TIMEOUT600s、migrate deploy专属LITELLM_PRISMA_MIGRATE_DEPLOY_TIMEOUT600s见 prisma_toolchain.py。运行时行为的测试覆盖可参考 tests/proxy_migration_tests/test_db_schema_migration.py 与 tests/proxy_migration_tests/test_prisma_toolchain.py。迁移完成之后当迁移 SQL 已生成、提交并合入目标分支下一步是发布新版litellm-proxy-extras包版本号同时联动根pyproject.toml中的 pin完整流程见 build_and_publish.mdcommitizen 自动 bumpcz bump --increment patch→ 清理dist/ build/ *.egg-info→uv build→twine upload。全文要点回顾改根 schema → diff 同步三份副本 →uv run --with testing.postgresql python ci_cd/run_migration.py name→ 遇到 STALE BRANCH 先 rebase 再重试、遇到 DESTRUCTIVE 先逐条核对 DROP 再考虑--allow-destructive→ 审查 SQL 后与 schema 一起提交。两条护栏的设计源头都是同一次落后分支静默删列事故——这也是这份 runbook 最值得记住的一课。【免费下载链接】litellmThe fastest, litest AI Gateway. Rust core with Python SDK. Call 100 LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]项目地址: https://gitcode.com/GitHub_Trending/li/litellm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表