用 Rust 重写 PostgreSQL:100% 通过回归测试的背后

日期:2026-07-11
主题:用 Rust 重写 PostgreSQL:100% 通过回归测试的背后
原文Postgres rewritten in Rust, now passing 100% of the Postgres regression tests
来源:Lobsters
领域:💻 编程语言


背景

2026 年 7 月,一个名为 pgrust 的开源项目在技术社区引起了不小的震动。它的目标直接而大胆:用 Rust 从头重写 PostgreSQL,并且——已经通过了 PostgreSQL 超过 4.6 万条回归测试中的 100%

这并非一个简单的"给 PG 穿 Rust 外衣"的玩具。pgrust 实现了 PostgreSQL 18.3 的全部核心子系统——SQL 解析器、查询规划器、执行引擎、事务管理器、MVCC 并发控制、WAL 预写日志,甚至包括 PL/pgSQL 存储过程语言。它磁盘兼容原生 PostgreSQL,可以直接挂载一个现有的 PG 18.3 数据目录启动。

项目作者 Malisper(前 Heap 公司 CEO,曾管理超 PB 级的 PostgreSQL 集群)只用了不到两个月就将这一切变成了现实。更引人注目的是,这场重写的背后,AI 编码代理充当了核心劳动力。

核心策略:重写而非包装

兼容层优先

pgrust 选择了与大多数 Rust 重写项目截然不同的路线:它不是通过 FFI 包装 C 代码来渐进式替换(如 pgxpgrx 的路径),而是从零开始用 Rust 实现 PostgreSQL 的每一个子系统。

这个决策有其合理性。PostgreSQL 的各个组件——尤其是存储引擎、锁管理器、查询优化器——之间的耦合度极高。试图在 C 代码中逐模块嵌入 Rust 替换,需要处理大量跨语言调用边界、内存所有权交接和 ABI 兼容性细节,复杂度呈指数级增长。pgrust 的方式虽然前期工作量大,但消除了这些接口摩擦。

关键的一步是:pgrust 保持与 PostgreSQL 的磁盘格式和网络协议完全兼容。这意味着:

回归测试作为 Oracle

pgrust 最聪明的一个设计决策是将 PostgreSQL 的回归测试套件作为最终的"正确性 Oracle"。

PostgreSQL 18.3 的回归测试包含 超过 4.6 万条 SQL 查询,覆盖了从基本数据类型(整数、浮点、JSON、几何、正则表达式)到高级特性(PL/pgSQL、触发器、物化视图、窗口函数、递归 CTE)的方方面面。每条查询都有一个预期的输出结果。

# pgrust 的回归测试运行方式
PGRUST_BIN="$PWD/target/release/postgres" \
  scripts/run-regression

这个测试运行器使用 pgrust 自带的 --initdb 初始化数据目录,然后逐条执行 PG 的回归测试文件,将 pgrust 的查询输出与预期输出进行 diff 比对。当所有 4.6 万+ 条测试的输出都与原生 PostgreSQL 完全一致时,就达到了 100% 兼容 的里程碑。

这是一个非常务实的策略——与其从零定义"什么是正确的数据库行为",不如复用 PostgreSQL 社区 40 年来积累的测试资产。这不仅验证了功能正确性,也保证了行为兼容性到细节层面。

AI 驱动的开发流程

从单代理到 17 代理协作

pgrust 的开发过程本身就是一篇值得研究的案例。Malisper 详细记录了从项目启动到接近完成的开发节奏:

第 1 天 — 搭建基础框架:只用了 3 个小时,作者就通过 Codex(Anthropic 的编码代理)构建了一个能运行 SQL 查询的最小原型。这个原型包括了存储层、SQL 解析器、并发控制和查询执行器四个核心模块。到第 1 天结束时,已经支持了 CREATE TABLESELECT/INSERT/UPDATE/DELETEJOIN/WHERE/ORDER BY/LIMIT 以及事务控制等基础功能。

第 2–7 天 — 性能实验与调试:这一阶段作者并行推进了两件事。一是用基准测试验证 Rust 实现的潜在优势——例如多线程模型相比 PG 的多进程模型在某些场景下能带来 3 倍加速;Rust 的正则表达式引擎(使用了 SIMD 优化)比 PG 的旧引擎快了 10 倍。二是修复并发控制中的竞态条件,这是数据库系统中最棘手的部分。

第 8–14 天 — 多代理并行开发:这是 pgrust 速度爆发期的关键。当需要实现大量独立功能(如 TOAST 存储、日期函数、视图支持)时,作者使用了一个名为 Conductor 的多代理协调工具:

我同时启动了多个代理,分别专注于不同的功能——一个负责构建 TOAST,一个负责日期函数,一个负责视图。Git 历史中可以看到多代理模式启动的那一刻。

经过迭代,作者最终同时运行了 17 个编码代理,直到电脑 CPU 满载。关键教训是:要让多代理工作,需要将任务切分为小到不会产生大量合并冲突的切片,每个代理完成一小块后立即合并回主分支。

"我不再阅读大部分代码"

Malisper 在开发过程中做了一个在传统工程视角看来相当激进的决定:不再阅读大部分由 AI 生成的代码

我曾是一家 120 人公司的 CEO。虽然我一直想阅读所有代码,但我做不到。我的工作是给团队设定护栏,并确保我有足够的可见性来理解问题出在哪里以及为什么。与一群 AI 代理协作也非常类似。

这背后的逻辑是:pgrust 处于非常早期的阶段,"先让它能工作"优先于"写出最优代码"。通过回归测试套件作为安全网,作者可以信任代理生成的代码,只在测试失败时深入排查。这种"信任但验证"的工程哲学,在 AI 辅助编程时代值得深思。

技术得失分析

值得关注的进展

1. 线程模型替代进程模型

PostgreSQL 使用多进程架构(每个连接 fork 一个子进程)有其历史原因——20 世纪 90 年代设计时,线程的稳定性远不如进程。但这个决定带来了实际成本:进程间上下文切换开销高、共享内存管理复杂、并行查询的启动成本大。

pgrust 从零开始就采用多线程模型,在简单的内存数据集基准测试中,单个查询快了 3 倍。更重要的是,pgrust 的新版本正在实现"每连接一线程"而非"每连接一进程"的模型,为内置连接池铺平了道路。

2. 现代化组件替换

Rust 生态中有大量经过实战检验的高质量库。pgrust 直接受益于:

3. 100% 回归测试兼容

这是 pgrust 最实在的成就。通过 4.6 万+ 条回归测试意味着 pgrust 在 SQL 语义层面与 PostgreSQL 几乎没有差异——这是任何"PostgreSQL 替代品"最难达到的目标。

必须指出的局限性

1. 性能尚未优化

pgrust 的 README 明确声明:"pgrust 尚未为生产环境做好准备,尚未进行性能优化。"查询规划器是后来添加的,还没有经过调优。这意味着目前的基准测试数字(无论好坏)都只是中间状态。

2. 扩展兼容性缺失

PostgreSQL 最强大的生态系统优势之一是其扩展机制。pgrust 目前与现有的 PG 扩展(如 PostGIS、pgvector、TimescaleDB)不兼容,PL/Python、PL/Perl 等过程语言扩展也暂不支持。这极大限制了实际部署场景。

3. 代码质量的不确定性

17 个 AI 代理并行生成代码,作者坦言"大量的垃圾代码混了进来"。虽然测试通过了,但代码的可维护性、安全性和长期演化能力仍是未知数。对于一个数据库这样对可靠性要求最高的系统软件,这可能是最大的隐患。

4. 社区分歧

Lobsters 和 Hacker News 上的讨论呈现出明显的两极分化。支持者认为这是 AI 辅助工程能力的"里程碑",质疑者则指出这更像是"用 LLM 做了个 PG 克隆,却绕过了 PG 社区 40 年的集体智慧"。后者更担心的是:一个 AI 生成、缺乏人工审查的数据库,真的可以替代经过几十年实战考验的 PostgreSQL 吗?

总结与展望

pgrust 是一个极具争议但也极具启发性的项目。从技术角度看,它证明了几个重要的事情:

但 pgrust 也暴露了 AI 辅助重写路线的深层问题:当代码的可读性、可维护性和安全性被"让测试通过"这一单一目标所取代,当 40 年的社区专业知识被压缩成训练数据中的统计模式,我们是否真的在进步?

pgrust 的路线图上有一些真正有趣的计划:内置连接池、无 Vacuum 存储引擎、针对 AI 生成 SQL 的运行时护栏。如果这些功能能在保持 100% PG 兼容性的同时实现,pgrust 将从"又一个 PG 克隆"进化为"更好的 PostgreSQL"。但这条路上还有很多未知数——性能调优、扩展生态、生产稳定性,每一个都是巨大的工程挑战。

正如项目 README 所言:"目标是让 PostgreSQL 变得更容易从内部改变。" 无论 pgrust 最终走向何方,它已经推动了关于"AI 如何参与核心基础设施软件开发"的讨论——而这个讨论本身,就值得我们的关注。