首页 / 文章 / pg_durable:PostgreSQL 内部的持久化执行框架
← 返回
AI技术

pg_durable:PostgreSQL 内部的持久化执行框架

✍️ zhirenhun 📅 2026/6/6 👁 113 阅读 ⏱ 28 分钟
pg_durable:PostgreSQL 内部的持久化执行框架

PostgreSQL 内部的持久化执行框架

Microsoft 开源的 pg_durable 是一个 PostgreSQL 扩展,为那些已经将状态保存在 Postgres 中、并希望摆脱拼凑 cron 任务、工作进程、队列和状态表来让后台工作变得可靠的团队,提供了长时间运行、容错的 SQL 函数支持。用 SQL 定义工作流,让 pg_durable 在每个步骤设置检查点(checkpoint),在崩溃、重启或步骤失败后自动恢复执行。

持久化执行(durable execution)如今已是行业标准模式,pg_durable 将其引入 Postgres 内部,无需额外的基础设施。这是我们推动"计算靠近数据"使命的一部分。

立即在 Azure HorizonDB 中体验 pg_durable——Microsoft 全新的 PostgreSQL 云服务,专为性能而设计,内置 pg_durable

这适合我吗?

适用人群

  • 后端和数据工程师——希望工作流与其操作的数据共存。
  • DBA 和 SRE——需要自动化 runbook,这些 runbook 必须能在重启后存活且可在 SQL 中审计。
  • 构建数据或 AI 管道的团队——需要按行、按文档或按批次进行持久化执行。

核心理念

pg_durable 函数是一个由 SQL 步骤组成的图(graph),PostgreSQL 在执行过程中逐步执行并设置检查点。如果数据库崩溃、重启或某一步骤失败,执行将从最后一个持久的检查点恢复,而无需手动重建状态。

[示意图:一个持久化函数扇出为三个并行查询——统计用户数、统计订单数、汇总收入——然后合并到仪表盘步骤中]

适用场景

  • 向量嵌入管道(Vector embedding pipeline):分块、调用 embedding API、写入 pgvector
  • 数据摄入管道(Ingest pipeline):暂存、去重、转换、发布大批量数据。
  • 定时维护:检测膨胀、通知、等待批准、执行后续操作。
  • 扇出聚合(Fan-out aggregation):并行执行独立查询,然后合并结果。
  • 外部 API 工作流:从 SQL 触发的数据增强、分类和 webhook 风格调用。

你现在可能正在用的替代方案

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

它解决的痛点

  • 长时间任务中途重启意味着重跑已经完成的工作。
  • 一行数据失败或一次 API 调用失败就导致手动清理和不确定的重放。
  • 长事务持有锁、增长 WAL,使批处理任务在较大规模下变得脆弱。
  • 应用层的并行处理为部分失败和状态漂移创造了更多机会。
  • 工作流逻辑分散在 SQL、工作进程、队列、仪表盘和状态表中。

你的架构会如何变化

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

何时不应使用

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

工作原理

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

局限性

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

功能特性

  • 持久化(Durable)——函数状态持久化到 PostgreSQL。在崩溃、重启和故障转移中存活。
  • SQL 原生(SQL-native)——使用可组合操作符在 SQL 中定义函数。
  • 数据库感知(Database-aware)——调度、条件和并行执行的一流原语。
  • 零基础设施(Zero infrastructure)——作为 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)''
);

软件包

标记版本从 GitHub 发布资产发布适用于 PostgreSQL 17 和 18(amd64)的 Debian 软件包。软件包命名为 pg-durable-postgresql-<PG 主版本>_<pg_durable 版本>-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 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 授予任何权限。安装扩展后,管理员必须显式授予应用角色访问权限。行级安全(Row-level Security, 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,默认为 postgres必须是超级用户——它绕过 RLS 来管理所有用户的实例。
  • 用户获得 df.instances / df.nodesSELECT + 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 回归测试)

快速、确定性的测试,用于核心 DSL 功能,使用 PostgreSQL 的标准测试框架。测试 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/

文档

  • 用户指南——完整的使用指南和示例。
  • MVP 指南——实现细节和内部原理。
  • 示例——示例规范和冒烟检查指南。

架构

pg_durable 是一个 PostgreSQL 扩展(使用 pgrx 构建)——所有内容都在 PostgreSQL 服务器内部运行,无需外部服务。该扩展提供了一个用于构建函数图的 SQL DSL,并注册了一个后台工作进程,在以下两个底层 Rust 库之上持久化地执行函数:

  • duroxide——一个持久化任务框架,提供编排运行时(确定性重放、检查点、子编排、定时器)。
  • duroxide-pg——为 duroxide 提供 PostgreSQL 后端的持久化状态提供者。它在扩展拥有的专用 duroxide.* schema 中持久化运行时状态(实例、历史记录、工作队列)。
┌────────────────────────────────────────────────────────────────────┐
│                             PostgreSQL                             │
│                                                                    │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │                 pg_durable extension (pgrx)                  │  │
│  │                                                              │  │
│  │  SQL DSL     ''sql'' |=> ''name'' ~> ''sql2''                     │  │
│  │              df.if() | df.join() | df.loop()                 │  │
│  │                                                              │  │
│  │  Background worker (hosts the duroxide runtime in-process)   │  │
│  │  ┌────────────────────────────────────────────────────────┐  │  │
│  │  │  duroxide        (orchestration runtime)               │  │  │
│  │  │  ┌──────────────────────────────────────────────────┐  │  │  │
│  │  │  │  duroxide-pg   (PostgreSQL state provider)       │  │  │  │
│  │  │  └──────────────────────────────────────────────────┘  │  │  │
│  │  └────────────────────────────────────────────────────────┘  │  │
│  │                                                              │  │
│  │  Schemas                                                     │  │
│  │    df.*         DSL graphs (nodes, instances, vars)          │  │
│  │    duroxide.*   runtime state (owned by duroxide-pg)         │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

如果你希望用 Rust、Python 或 Node 编写持久化函数,同时仍将状态持久化在 PostgreSQL 中,可以直接从宿主语言使用 duroxide 和 duroxide-pg——pg_durable 是当你更倾向于用 SQL 编写时,在这对库之上构建的产物。

状态

预览版(Preview)——该项目当前处于预览阶段。

支持

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

行为准则

本项目已采用 Microsoft 开源行为准则。如需更多信息,请参阅行为准则常见问题解答,或通过 opencode@microsoft.com 联系。

安全

Microsoft 非常重视其软件产品和服务的安全性。请勿通过公开的 GitHub Issues 报告安全漏洞。安全报告说明请参阅 SECURITY.md

隐私与遥测

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

商标

本项目可能包含项目、产品或服务的商标或标识。Microsoft 商标或标识的授权使用须遵守并遵循 Microsoft 商标与品牌指南。在本项目的修改版本中使用 Microsoft 商标或标识不得引起混淆或暗示 Microsoft 的赞助。第三方商标或标识的使用须遵守第三方相关政策。

许可证

PostgreSQL License(PostgreSQL 许可证)


原文链接:https://github.com/microsoft/pg_durable

——

🧑‍💻

zhirenhun

一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。

← 上一篇
rsync Claude 辅助开发争议数据分析报告
下一篇 →
Meta 确认数千 Instagram 账户遭黑客利用 AI 聊天机器人劫持

📌 相关推荐

提示注入的理论基础:角色混淆(Prompt Injection as Role Confusion)
2026/6/23
GLM-5.2 本地部署指南
2026/6/23
Moebius: 0.2B 轻量级图像修复框架,实现10B级别的性能
2026/6/23
← 返回文章列表