pg_durable:Microsoft 开源数据库内持久执行
概述
- pg_durable 被视为 2026 年更广泛趋势的一部分,即“Postgres 作为队列/编排器”,与其他基于 PG 的作业/队列系统并列。
- 讨论分成两派:一派对“把计算带到数据旁边”感到兴奋,另一派则强烈偏好将编排和业务逻辑放在应用代码中。
数据库内持久执行 vs 外部编排器
- 支持者认为:如果 Postgres 是主要的有状态组件,把工作流保留在数据库内可以简化技术栈,避免额外基础设施(例如 Temporal、Airflow),降低延迟/往返次数,并且让数据库快照同时捕获数据和工作流状态。
- 批评者认为:对于跨系统工作流,外部编排器和 DAG 调度器(Airflow、类似 Temporal 的系统)更合适;它们能让控制流保留在熟悉的语言和工具链中。
提到的用例与收益
- 长时间运行/可恢复的工作流、ETL/AI 管道、具有 exactly-once 语义和检查点回放的类 cron 作业。
- 能够在包含工作流的情况下恢复“某个时间点”的状态,这对与数据库状态紧密耦合的 ETL 和 AI 管道很有用。
- 当 HTTP 调用和处理主要以数据为中心,并且已经以数据库为目标时,这种方式尤其有帮助。
担忧与批评
- “闻起来像存储过程”:担心业务逻辑隐藏、可观测性差、扩展压力集中在数据库上、IO 和外部 API 集成有限。
- 开发体验问题:SQL/DSL 语法别扭、调试困难、与主流语言和 CI/CD 流程相比工具不足。
- 担心给本来就难以扩展的数据库再加上长时间运行的作业。
工具、版本管理与测试
- 多条评论询问如何对持久函数进行版本管理、测试、调试和发布。
- 有人认为所有数据库对象(函数、触发器)本来就应该纳入源代码管理和迁移;也有人说大多数团队并没有成熟的数据库工作流,因此把逻辑放在代码里更安全。
pg_durable 的行为方式(来自讨论串)
- 工作流通过
df.start(...)定义并启动,返回一个实例 ID。 df.wait_for_signal只针对单个实例,并且在该实例内是“exactly once”;重复调用df.start会创建新的实例。- 超时和错误处理会以工作流状态和失败实例的形式暴露出来,但详细的错误语义对读者来说仍然有些不清楚。
元讨论:Postgres、扩展与 Rust
- 关于 Postgres 是否足够可扩展的旁支讨论(许多人提到其丰富的扩展生态),以及是否应当用 Rust 重写并采用更模块化架构的呼声。
- 有人认为数据库内编排是“内部平台效应”;也有人认为这只是对成熟、可扩展系统的一种务实复用。