声明式模式 2.0 与 pg-delta

声明式模式 2.0 与 pg-delta

💡 原文英文,约2300词,阅读约需9分钟。
📝

内容提要

Supabase 发布声明式模式 2.0,以自研开源工具 pg-delta 取代 migra 生成迁移。新引擎基于 Postgres 系统目录进行差异比较,支持 RLS 策略、授权、视图、分区、域及扩展对象,并按依赖图排序。新项目默认启用,旧项目需在 config.toml 中开启。pg-delta 仍为 alpha,不处理数据变更。

🔎

延伸解读

从 migra 到 pg-delta:覆盖范围与对象归属的改进

migra 无法识别域、发布、注释等对象,且只能按 schema 过滤,无法区分 auth 等 Supabase 管理的部分与用户自有对象。pg-delta 基于系统目录逐对象判断归属,支持 RLS 策略、授权、视图、分区、域及扩展对象,并按依赖图排序。这意味着生成的迁移更完整,但用户仍需审查输出,因为引擎优先覆盖而非最小破坏。

启用方式与迁移注意事项

新项目默认启用 pg-delta,旧项目需在 config.toml 中添加 [experimental.pgdelta] 并设置 enabled = true,且要求 CLI 2.119 或更高版本。若之前使用 migra 的声明式模式,首次 db pull 可能产生追赶迁移。需将脚本从 db diff 切换到 db schema declarative sync。设置 enabled = false 可回退到 migra。

破坏性变更与数据边界

pg-delta 优先保证覆盖和正确性,可能生成破坏性迁移,例如重命名列会输出 drop 后 add,直接应用会丢失数据。CLI 会标记破坏性操作,但无法识别重命名意图,需手动改写。此外,pg-delta 不处理数据变更,仅生成模式变更;扩展配置行(如 pg_cron 任务、pgmq 队列)通过扩展 API 处理,存储桶行目前不纳入差异比较。

当前限制与适用场景

pg-delta 仍为 alpha,可能发生破坏性变更。它不提供零停机部署编排,输出仅为普通 SQL 迁移,生产环境安全执行仍需自行负责。不支持 ORM 插件或 TypeScript schema DSL,仅支持 Postgres 14 至 18。若生成迁移有误,可提交 issue 或支持工单。对于需要精细控制迁移过程的团队,需评估这些限制。

❓

Q&A

Supabase 声明式模式 2.0 是什么?它和之前的版本有什么主要区别?

声明式模式 2.0 是 Supabase 在 2025 年 10 月 2 日发布的更新,用自研开源工具 pg-delta 取代了原先的 migra 来生成迁移。主要区别在于 pg-delta 基于 Postgres 系统目录进行差异比较,支持 RLS 策略、授权、视图、分区、域及扩展对象,并按依赖图排序,而 migra 不支持这些。

为什么 Supabase 要用 pg-delta 替换 migra?

因为 migra 存在局限性:它不理解域、发布或注释,这些变更不会出现在差异中;只能按 schema 级别过滤,无法区分哪些对象属于用户、哪些属于 Supabase(如 auth schema 与用户触发器);且扩展它需要对抗其设计。因此 Supabase 从头编写了 pg-delta。

如何为现有项目启用 pg-delta?

需要 Supabase CLI 2.119 或更高版本。在 config.toml 中添加 [experimental.pgdelta] 块并设置 enabled = true。新项目默认启用,旧项目需手动添加。设置 enabled = false 可继续使用 migra。

pg-delta 生成迁移的工作流程是怎样的?

工作流程分四步:1. 在 supabase/schemas/ 下声明 schema;2. 运行 supabase db schema declarative sync 生成迁移;3. 审查并应用迁移;4. 修改 schema 后再次同步。CLI 会对比 schema 文件与迁移历史,输出差异 SQL。

pg-delta 目前有哪些限制或不支持的功能?

pg-delta 仍为 alpha,不处理数据变更(只生成 schema 变更),不支持零停机部署编排、ORM 插件或 TypeScript schema DSL,且仅支持 Postgres 14 到 18。存储桶(storage.buckets)的行目前不进行差异比较。

pg-delta 如何处理扩展管理的对象(如 pg_cron 任务或 pgmq 队列)?

pg-delta 不会为扩展管理的对象生成 create table 或 drop table,而是通过扩展自身的 API 进行变更。例如,pg_cron 任务使用 cron.schedule_in_database 和 cron.unschedule,pgmq 队列使用 pgmq.create 和 pgmq.drop_queue,并且 CLI 会将删除操作标记为破坏性。

🏷️

标签

➡️

继续阅读