pg_durable: 微软开源数据库内持久化执行

Hacker News Top 工具

摘要

微软开源了pg_durable,这是一个PostgreSQL扩展,支持长时间运行的SQL函数的持久化执行,具有自动检查点和容错恢复功能。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/06/05 17:09

microsoft/pg_durable

来源:https://github.com/microsoft/pg_durable
网站(https://microsoft.github.io/pg_durable/)· 文档· 快速示例· GitHub(https://github.com/microsoft/pg_durable)许可证
PostgreSQL 17 和 18(https://www.postgresql.org/)

PostgreSQL 内的持久化执行

为那些已经将状态保存在 Postgres 中,并希望不再拼凑 cron 任务、工作进程、队列和状态表来使后台工作变得可靠的团队提供长时间运行、容错的 SQL 函数。在 SQL 中定义工作流,让 pg_durable 对每一步进行检查点记录,并在崩溃、重启或步骤失败后恢复。持久化执行现在是一种标准的行业模式,pg_durable 将其引入 Postgres 内部,无需额外的基础设施服务。这是我们使命的一部分——让计算靠近数据。

这适合我吗?

适用人群

  • 后端和数据工程师,希望工作流与所操作的数据共存。
  • 数据库管理员和 SRE,需要自动化能够在重启后存活并以 SQL 形式审计的运行手册。
  • 构建数据或 AI 管道的团队,需要按行、按文档或按批次的持久化执行。

核心理念

pg_durable 函数是一个由 SQL 步骤构成的图,PostgreSQL 会逐步执行并对其进行检查点记录。如果数据库崩溃、重启或某一步骤失败,执行将从最后一个持久化检查点恢复,而无需手动重建状态。

此类工作负载的适用场景

  • 向量嵌入管道:分块、调用嵌入 API,然后更新插入到 pgvector 中。
  • 数据摄入管道:暂存、去重、转换并发布大批量数据。
  • 计划性维护:检测膨胀、通知、等待批准,然后执行下一步操作。
  • 扇出聚合:并行运行独立查询,然后合并结果。
  • 外部 API 工作流:从 SQL 中进行数据丰富、分类和 webhook 风格的调用。

你当前可能采取的做法

  • pg_cron 加上任务表、状态列、重试计数器和轮询工作进程。
  • 外部编排器(如 Airflow、Temporal、Step Functions 或 Argo)回调 Postgres。
  • 队列加工作进程加独立的状态表来协调重试和部分完成。
  • 一个 plpgsql 过程,在崩溃或长时间运行的事务迫使你重新开始时失效。

它解决的问题

  • 长时间任务中途重启意味着重复执行已成功完成的工作。
  • 单行失败或单次 API 调用失败导致手动清理和不确定的重放。
  • 长事务持有锁、增加 WAL,使批处理任务在较大规模下变得脆弱。
  • 应用层的并行工作引入了更多部分失败错误和状态漂移的隐患。
  • 工作流逻辑分散在 SQL、工作进程、队列、仪表盘和状态表中。

你架构中会发生的变化

  • 工作流定义转移到 SQL 中,并以 df.start(...) 开始。
  • 重试状态、进度跟踪和检查点记录转移到 Postgres 中,而不是自建的应用代码。
  • 部分应用层工作进程、队列消费者或调度粘合剂可以完全消失。
  • 运维可见性来自 Postgres 表(如 df.instances),使用与数据相同的认证和备份模型。

何时不应使用

  • 任务已经是单一的 INSERT ... SELECT 或一条普通 SQL 语句。
  • 你需要亚毫秒级的同步请求处理,而不是持久化的后台执行。
  • 你无法在 Postgres 环境中安装扩展或运行后台工作进程。
  • 工作流主要位于 Postgres 之外,并跨越许多异构系统。
  • 你需要无法清晰映射为 SQL 步骤、分支、循环或 HTTP 调用的任意应用逻辑。

工作原理

  1. 在 SQL 中使用可组合的操作符(如 ~>|=>)定义工作流。
  2. 使用 df.start() 启动工作流,并获取一个实例 ID。
  3. 让运行时在每一步之间通过检查点持久化执行每个步骤。
  4. 在工作流运行期间或完成后,从 PostgreSQL 查询状态和结果。

局限性

该模型有意采用 SQL 形式。如果某一步需要任意代码、非 HTTP 的 SDK 或丰富的内存控制流,你可能需要将该逻辑包装在 SQL 函数中、将其暴露为 df.http() 的 HTTP 端点,或针对系统的该部分使用通用编排器。

特性

  • 持久化 — 函数状态持久化到 PostgreSQL。能够承受崩溃、重启和故障转移。
  • SQL 原生 — 使用可组合的操作符在 SQL 中定义函数。
  • 感知数据库 — 提供一流的原语用于调度、条件和并行执行。
  • 零基础设施 — 作为 PostgreSQL 扩展运行。无需 Redis、Temporal 或外部服务。

快速示例

-- 一个按步骤处理数据的持久化函数
SELECT df.start(
    'SELECT id FROM documents WHERE processed = false LIMIT 100'
    |=> 'batch'
    ~> 'UPDATE documents SET processed = true WHERE id = ANY($batch)'
);

软件包

标记版本发布时会发布针对 PostgreSQL 17 和 18(amd64)的 Debian 软件包,这些包位于 GitHub 发布资产生成中。软件包命名为 pg-durable-postgresql-<版本>-1_<架构>.deb,并将扩展库、控制文件和 SQL 升级文件安装到相应的 PostgreSQL 安装目录中。

安装软件包后,将 pg_durable 添加到 shared_preload_libraries,重启 PostgreSQL,并在已配置的 pg_durable 数据库中创建扩展:

CREATE EXTENSION pg_durable;

默认的 pg_durable 数据库是 postgres;有关后台工作进程配置和权限设置,请参见用户指南

发布资产生成还包括用于从源码构建的源码归档。

开发安装

先决条件

  • PostgreSQL 17 或 18
  • Rust(nightly)
  • cargo-pgrx(https://github.com/pgcentralfoundation/pgrx)0.16.1

GitHub Codespace

主分支预构建会安装 PostgreSQL 17、构建 pg_durable,并在 ~/.pgrx 下准备一个包含扩展的本地集群。PostgreSQL 不会保持运行状态,请在开始工作时启动它。

# 启动 PostgreSQL
./scripts/pg-start.sh

# 连接
~/.pgrx/17.*/pgrx-install/bin/psql -h localhost -p 28817 -d postgres

在没有就绪预构建的分支上,运行 pg-start.sh——它会在首次运行时构建并安装扩展(预计需要几分钟):

./scripts/pg-start.sh

其他环境

本地开发和 Dev Container

VS Code Dev Container(.devcontainer/)预装了 Rust、cargo-pgrx 和 PostgreSQL 17。对于裸机本地机器,请先按照 .devcontainer/onCreateCommand.sh 中的步骤安装工具链。

# 构建、初始化 PostgreSQL 并安装扩展
# 这需要一些时间——可以先去忙别的事情
./scripts/pg-start.sh

# 连接到本地 pgrx PostgreSQL 实例
~/.pgrx/17.*/pgrx-install/bin/psql -h localhost -p 28817 -d postgres

pg-start.sh 会引导新的本地数据目录,创建一个 postgres 超级用户,并为当前 OS 用户创建一个匹配的超级用户角色,以便默认的本地 psql 使用继续正常工作。如果你想强制使用规范的引导角色,请使用 -U postgres

Docker

# 构建并测试
./scripts/test-e2e-docker.sh --rebuild

# 可选:部署到 ACR(用于自定义内置 pg_durable 的 PG17 镜像)
./scripts/deploy-acr.sh

多用户设置

CREATE EXTENSION pg_durable 不会PUBLIC 授予任何权限。安装扩展后,管理员必须显式授予应用程序角色访问权限。行级安全性(RLS)确保每个用户只能看到和管理自己的持久化函数实例和节点。

向应用程序角色授予权限:

-- 在 CREATE EXTENSION 之后向特定角色授予权限
SELECT df.grant_usage('app_role');

或者,创建一个间接角色并将应用程序角色设为其成员:

-- 为 pg_durable 访问创建一个共享角色
CREATE ROLE pg_durable_user NOLOGIN;
SELECT df.grant_usage('pg_durable_user');

-- 将成员资格授予应用程序角色
GRANT pg_durable_user TO app_backend, etl_service;

有关完整的单个授权列表、撤销权限以及保护升级后的安装,请参见用户指南 — 权限授予部分。 注意: GRANT EXECUTE ON ALL FUNCTIONS 仅适用于授权时存在的函数。在通过 ALTER EXTENSION pg_durable UPDATE 升级 pg_durable 后,重新运行 df.grant_usage('role')(或重新发出手动授权),以便新函数可访问。

关键点:

  • 后台工作进程角色(pg_durable.worker_role GUC,默认值:azuresu必须是超级用户——它绕过 RLS 来管理所有用户的实例。
  • 用户对 df.instances / df.nodes 拥有 SELECT + INSERT 权限,对实例的 df.cancel() 操作拥有列级 UPDATE (status, updated_at) 权限。
  • 标识列(submitted_by)用户无法修改。
  • df.vars 使用每个用户的作用域 — 每个用户通过 owner 列和 RLS 拥有自己的变量命名空间。超级用户绕过 RLS,但 DSL 函数仍然通过显式过滤器将作用域限制到调用用户。避免在明文中存储密钥。

持续集成

所有拉取请求在合并前必须通过以下检查:

  1. 格式检查cargo fmt --check
  2. Clippy 和测试cargo clippy、单元测试(cargo pgrx test pg17)、pg_regress 测试和 E2E 测试

CI 工作流定义在 .github/workflows/ci.yml 中。它使用 pgrx 下载和管理 PostgreSQL。

测试

pg_durable 有两个测试套件:

pg_regress 测试(标准 PostgreSQL 回归测试)

使用 PostgreSQL 的标准测试框架进行快速、确定性的核心 DSL 功能测试。测试 SQL 位于 sql/,预期输出位于 expected/,PGXS 在根 Makefile 中配置。

make test-regress    # 完全重置并运行
make installcheck    # 仅运行(PostgreSQL 必须已运行)

E2E 测试(综合场景测试)

使用 pgrx PostgreSQL 进行复杂的本地集成测试:

./scripts/test-e2e-local.sh                          # 所有本地 SQL E2E 测试,包括特殊的重启/配置阶段
./scripts/test-e2e-local.sh 04_parallel               # 特定测试
./scripts/test-e2e-local.sh --default-build-phases    # 仅 default-build 阶段组

详情请参见 tests/e2e/

文档

架构

pg_durable 是一个 PostgreSQL 扩展(使用 pgrx(https://github.com/pgcentralfoundation/pgrx)构建)——所有内容都在 PostgreSQL 服务器内运行,无需外部服务。该扩展公开了一个用于构建函数图的 SQL DSL,并注册了一个后台工作进程,该工作进程在两个更低层的 Rust 库之上持久地执行这些函数:

  • duroxide(https://github.com/microsoft/duroxide) — 一个持久化任务框架,提供编排运行时(确定性重放、检查点、子编排、定时器)。
  • duroxide-pg(https://github.com/microsoft/duroxide-pg) — 一个基于 PostgreSQL 的状态提供程序,用于 duroxide。它将运行时状态(实例、历史记录、工作队列)持久化在扩展拥有的专用 duroxide.* 模式中。
┌────────────────────────────────────────────────────────────────────┐
│ PostgreSQL                                                         │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │ pg_durable 扩展 (pgrx)                                       │  │
│  │                                                              │  │
│  │  SQL DSL 'sql' |=> 'name' ~> 'sql2'                        │  │
│  │  df.if() | df.join() | df.loop()                           │  │
│  │                                                              │  │
│  │  后台工作进程(在进程中托管 duroxide 运行时)                │  │
│  │  ┌────────────────────────────────────────────────────────┐ │  │
│  │  │ duroxide(编排运行时)                                  │ │  │
│  │  │  ┌──────────────────────────────────────────────────┐ │ │  │
│  │  │  │ duroxide-pg(PostgreSQL 状态提供程序)            │ │ │  │
│  │  │  └──────────────────────────────────────────────────┘ │ │  │
│  │  └────────────────────────────────────────────────────────┘ │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                    │
│  模式                                                              │
│  df.* DSL 图(节点、实例、变量)                                    │
│  duroxide.* 运行时状态(由 duroxide-pg 拥有)                      │
└────────────────────────────────────────────────────────────────────┘

如果你更愿意用 Rust、Python 或 Node 编写持久化函数,同时仍然将状态持久化到 PostgreSQL,你可以直接从宿主语言中使用 duroxide 和 duroxide-pg——pg_durable 是在这对工具之上构建的,适合你更愿意用 SQL 编写的情况。

状态

预览版 — 该项目目前处于预览阶段。

支持

请使用 GitHub Issues 报告错误和提出功能请求。不要通过公开的 GitHub Issues 报告安全漏洞;请按照 SECURITY.md 中的说明操作。

行为准则

该项目已采用 Microsoft 开放源代码行为准则(https://opensource.microsoft.com/codeofconduct/)。有关更多信息,请参阅行为准则常见问题解答(https://opensource.microsoft.com/codeofconduct/faq/),或通过 [email protected] 联系。

安全性

Microsoft 非常重视我们软件产品和服务的安全性。请不要通过公开的 GitHub Issues 报告安全漏洞。有关安全报告说明,请参见 SECURITY.md

隐私与遥测

pg_durable 不会向 Microsoft 发送遥测数据。

商标

本项目可能包含项目、产品或服务的商标或徽标。授权使用 Microsoft 商标或徽标必须遵守且遵循 Microsoft 的商标与品牌指南(https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general)。在修改版项目中使用 Microsoft 商标或徽标不得引起混淆或暗示 Microsoft 赞助。任何第三方商标或徽标的使用均须遵守其各自政策。

许可证

PostgreSQL 许可证

相似文章

持久化执行:硬核方式

Hacker News Top

一本教程指南,教你如何受Kubernetes the hard way启发,从零开始使用Go和Postgres构建持久化执行引擎。

PgDog 获得融资,即将登陆您的数据库

Hacker News Top

PgDog 是一个开源代理,使 Postgres 实现水平扩展,已从 Basis Set、YC 等机构获得 550 万美元融资。该工具已在生产环境中每秒处理超过 200 万次查询。

PgDog

Product Hunt

PgDog 是一款无需修改应用程序即可扩展 PostgreSQL 的工具,提供连接池和负载均衡功能。

pgBackRest 将继续发展

Lobsters Hottest

pgBackRest,一款流行的 PostgreSQL 备份工具,宣布将在一系列赞助商(包括 Amazon Web Services、Supabase 等)的支持下继续开发,确保长期可持续性。