跳过正文
  1. AI/

AI 用 Rust 重写 PostgreSQL?别逗了

·7712 字·16 分钟· ·
冯若航
作者
冯若航
Pigsty 创始人, @Vonng
目录

上周,一个叫 pgrust 的项目冲上 Hacker News 头条:用 Rust 重写 PostgreSQL,跑通 PG 18.3 核心回归套件里的 46,066 条查询,还预告了“事务快 50%、分析快 300 倍”。二十四小时内,GitHub 星数从 122 涨到 1,499。 中文媒体的标题已经在路上了:“AI 用 Rust 重写了 PostgreSQL”。

不过老冯这篇文章想说的是:这个项目最有价值的地方,恰恰是所有报道都没写的那部分 —— 它用两个月时间,亲手证明了自己想推翻的东西。

引子:一天十二倍
#

pgrust 的作者 Michael Malis 不是无名之辈:他在 Heap 管过 PB 级的 Postgres 集群, 写过几十篇 Postgres 内核剖析(malisper.me 那个系列),当过 120 人公司 Freshpaint 的 CEO, 还表演过用递归 CTE 写 Lisp 解释器。一个真懂 PG 内核的人,拿着最新的 AI 编码工具做实验 —— 这不是 “外行用 AI 造数据库”。

七月九日,项目被人转到 HN,688 分,五百八十多条评论(截稿时),星数一天翻了十二倍。README 上挂着三个数字: 跑通 PostgreSQL 18.3 核心回归套件里的 46,066 条查询;一个未发布的新版本在 TPC-C 上比 PG 快 50%;分析负载快约 300 倍。

老冯正好也 token 过剩,让 Claude Fable 5 和 Codex 5.6 也来验验货,练练手,看了下这个项目。


一、这个项目死过一次
#

大多数人不知道,pgrust 还有个前世,现在这个版本已经转生过一次了。

pgrust 的第一世界始于四月。Malis 从零开始,用 Codex 写 Rust 版 Postgres:两周写出 25 万行,通过三分之一的回归测试; 随后开到 8 个 Codex 账号(每月 1,600 美元),十几二十个 agent 并行,两周合并 280 个 PR,四月底冲到 67%,五月初宣布 96%。风头正劲。

然后,六月二十三日,这套代码被整体归档,扔进一个叫 archive/pre-fabled-2026-06-23 的分支,再没动过。

第二世转生从六月十二日开始,方法论彻底换了。作者在 HN 亲口交代:是先用 c2rust 把 PostgreSQL 的 C 源码机械翻译成 Rust —— 得到一堆 unsafe 但能通过 PG 核心 SQL 回归测试的代码,c2rust 把 Postgres 拆成了约一千个 crate —— 然后让 Claude 逐个 crate 做惯用化重写,配了三个流水线技能:挑下一个 crate、重写、审计。 绝大多数 crate 都走了这条流水线,parser 等少数生成代码仍然保留着大块机械翻译与 unsafe。

这一版的速度是骇人的。首个提交在 6 月 12 日,提交信息是 “Bootstrap pgrust: catalog, seam architecture, and porting skills”; 到 6 月 24 日收工,13 天,7,103 个 commit,峰值一天 1,419 个。 git 作者统计栏是这样的:Michael Malis,6,264 个;Claude Fable 5,署名 832 个;合伙人 Jason Seibel,7 个。 产出 240 万行 Rust、3,525 个文件、1,464 个 crate。6 月 25 日发布,宣布跑通 PG 18.3 核心回归 schedule 与 isolation 测试, 并且——磁盘格式兼容,能直接从一个现成的 PostgreSQL 18.3 数据目录启动。

“从原版数据目录直接启动”听起来像魔法,但其实拆开看很朴素:

它的血管里流的就是 PostgreSQL 的代码。这不是重写,是翻译。

请注意这条时间线说明了什么。一个手握无限 AI 算力、对 PG 内核了如指掌的专家,用两个月的真金白银回答了一个问题:代码可以被 AI 凭空重造吗?答案是不能。 从零重写的一代死了,直译 PG 本体的二代活了。他最后能交出满分答卷,靠的是把 Postgres 三十年的代码沉积原封不动搬进来,连考卷都是 PG 社区出的。 这场实验最扎实的成果,就是它自己营销话术的反面。

顺带一个注脚,能看出发布时的仓促:240 万行 Rust 译文中,我没找到一个 .rs 源文件保留 PostgreSQL 的版权头, 归属声明只存在于测试数据目录的一份 README 里。翻译拿走了文本,顺手掐断了系谱。还从宽松的 PostgreSQL 类 BSD 许可证换成了 AGPLv3。


二、你测试的到底是什么?
#

先把敬意给足,这部分我请 Fable 验证过。

仓库 vendor 了 PG 18.3 的官方测试文件。Claude 抽了 18 个文件 —— 包括排课表 parallel_schedule(230 项全量)、join.outnumeric.outselect_parallel.outplpgsql.out、isolation 的排课表——与上游 REL_18_3 标签逐字节比对, 全部一致。没有篡改期望输出,没有删减题目。runner 脚本逻辑干净,任何人 clone 下来配一个 psql 客户端就能复现。 满分没有作弊,这在 vibe coding 泛滥的今天已属难得。

但满分有四条边界,转述者一条都没提。

其一,那个开箱即用的 runner 把约 230 个 SQL 脚本拆开串行执行。真正的 pg_regress 会并发跑 parallel group, 用二十来个会话互相踩踏来考验锁和并发——这条公开路径没压过一丝回归调度并发。而且服务端用 -F 启动,fsync 也是关着的。 回归测试这么干很正常,不算作弊;但这个分数只证明功能输出,不证明持久性。其二,公开仓库没有 CI,满分状态没有持续验证。 其三,isolation 测试需要另备一棵 PG 源码树,不在开箱路径里。 其四,也是最响的—— “TPC-C 快 50%、分析快 300 倍” 属于一个尚未发布的新版本: 没有代码,没有 benchmark 配置,没有硬件说明。

作者在 HN 补充说,新版本不只换了列存格式,还上了批式执行、并行化和更快的哈希表; 跑的是 ClickBench,比 ClickHouse 慢 2 倍。而原生行存 PG 在 ClickBench 上本来就落后 ClickHouse 两三个数量级 —— 这是公开榜单的常识。 300 倍这个数字的数学并不神秘。很多 PG 分析扩展(比如 DuckDB 缝合扩展)在 ClickBench 上都展现出比原生 PG 快几百倍的能力。

所以“比 PG 快 300 倍、比 CH 慢 2 倍”在算术上完全自洽。但这已经不是 Rust 对 C 的同构性能对比,而是存储布局、执行模型和并行策略一起换了,或者是额外缝合了一些分析扩展进来。 代码与 benchmark 工件公开之前,谁也拆不出这 300 倍各自从哪来。无论如何,它证明的是架构换代有空间,不是“AI 把 C 翻成 Rust 就凭空快了 300 倍”。 PgCat 的作者 levkk 在评论区只问了一句:fsync 开了吗?回归测试可查不出坏的 IO 模式。这一问,顶一万字。

平心而论,作者本人的措辞相当克制:不是生产就绪,没做性能优化,现有扩展不兼容,白纸黑字写在 README 里。失控的从来是转述。


三、Bun:对照实验
#

与此同时发生的另一件事情值得一提。

有人会拿 Bun 反驳:JavaScript 运行时不是刚用 AI 从 Zig 翻成 Rust,还成了吗? 但在老冯看来:Bun 非但不是反例,它和 pgrust 凑成了一组教科书级的对照实验。

先看方法,两者几乎同构。Jarred Sumner 在 7 月 8 日发布的复盘写得很清楚:迁移发生在 5 月 3 日到 14 日; 不做从零重写 —— 因为重写要冻结一年的功能开发,而是让 Claude 先生成一份 Zig 模式到 Rust 模式的移植指南,然后把每个 .zig 文件机械地移植成 .rs 文件, 做一个“看起来像把 Zig 代码转译成 Rust”的版本,发布之后再逐步重构成惯用写法。约 50 个 Claude Code 动态工作流,跑了 11 天。 而且 Bun 的出身本来就是翻译——它的第一版就是把 esbuild 的转译器从 Go 逐行移植到 Zig 的产物。

再看巧合,巧到像安排好的。Bun 用的是 Claude Fable 5 的预发布版本;pgrust 二代的 git 里,Fable 署名了 832 个 commit。 Bun 官方复盘口径是 6,778 个 commit、101 万行新增的一个 PR(剔除 merge 后,动画重放的是 6,502 个); pgrust 是 7,103 个 commit、240 万行。一个 11 天,一个 13 天。同一个模型,同一种方法,同一个初夏。

Bun(Zig → Rust)pgrust(C → Rust)
方法机械移植,后续惯用化c2rust 直译,逐 crate 惯用化
模型Claude Fable 5(预发布)Claude Fable 5(832 个署名提交)
工期11 天13 天
体量101 万行新增,6,778 commits240 万行,7,103 commits
验证 oracle自家百万断言测试套件(TypeScript 写的,语言无关)PG 核心 SQL 回归 + isolation 套件
翻译对象自己的活系统别人的文本
结局已进生产:Claude Code v2.1.181 起跑在其上,Prisma 公开背书星数 1,499,生产部署为零

真正拉开命运差距的变量落在最后两行:信任拓扑。Bun 翻译的是自己的活系统——团队、测试资产、用户、商标、问责主体,一个都没换。 翻译完成后直接灌进自家生产管道验毒:Claude Code 跑在上面,Prisma 拿真实故障场景复测后公开点赞。船还是那条船,只是换了引擎。 pgrust 翻译的是别人的文本,把系统留在了原地——复印了一张船的图纸。

而且,即便是这个最优条件下的翻译,账单也是公开可见的:迁移过程引入了 19 个已知回归,官方称已经全部修掉;token 成本按 API 价格估算约 16.5 万美元; 外加一场信任风波——Zig 作者 Andrew Kelley 发文反驳,指出所谓性能提升来自 Zig 一直就支持的 LTO,还称 Bun 团队私下承认没有做 fuzzing。 Bun 官方却明说,Zig 时代已经用 Fuzzilli 对 runtime API 做 24×7 fuzzing。两边口供正面打架,至少有一边把话说过了头。 lobste.rs 的看客给这套操作起了个名字,叫 vibe porting。在位者带着全部资产做翻译,尚且要付这些代价。两手空空的 fork,拿什么付?

所以 Bun 划下的边界比任何论证都清晰:翻译这门技术成立了,但它首先是在位者的工具。它最擅长给一条正在航行的船换引擎;想靠一张译过的图纸造出第二支船队,远远不够。


四、四层知识,翻译只搬走两个
#

现在回答核心问题:通过全部回归测试,到底继承了 PostgreSQL 的多少?要回答它,得先数清楚 PG 的可靠性知识住在哪。我数出四层。

**第一层,住在单元测试里。**测试套件是已固化、可携带的知识。这 46,066 条回归查询,背后压着三十年功能语义与故障修复的沉积。pgrust 完整拿到了这张核心考卷。

**第二层,住在代码形状里。**那些看似多余的防御性检查、怪异到反直觉的执行顺序、“不要动这里,见 2004 年那个线程”的注释 —— 修 bug 的人走了,修复的形状留在代码里。 这是化石化的默会知识。直译能把化石一起搬走,从零重写会把它全部扬掉——这就是 pgrust 一代死、二代活的技术解释。 Bun 那 19 个回归也从反面印证了这层的脆弱:绝大多数出在两种语言里语法相同、语义不同的地方。化石在翻译中会碎,只是碎得比重写少。

**第三层,住在档案里。**为什么这么修、另外三种方案为什么被否、当年争论的输家提出过什么反例 —— 三十年 pgsql-hackers 邮件列表里的因果链。代码翻译本身带不走,它不在代码里。

**第四层,住在人脑里。**评审一个 patch 时 “这里会不会踩到复制槽的雷” 的直觉。谁也带不走。

现在看杀招。pgrust 给自己的定位是“让 Postgres 更容易被从内部改变”。可是 —— 跑起来只需要前两层,改下去需要的恰恰是后两层,正是代码翻译不会自动带走的那两层。 方法与使命,互相拆台。

有人会说:考卷够厚不就行了?PG 自己的历史给出了三个否定答案。 2018 年的 fsyncgate:PG 对 Linux fsync 错误语义的假设错了二十年,最后以“fsync 失败直接 PANIC”收场 —— 这类知识一半在代码里,一半在老兵的酒桌上。 9.3 的 multixact 数据损坏长征: 原班人马、全部上下文在手,尚且修了一年多的小版本才收干净。 最漂亮的是 2020 年:Jepsen 拿一套全新的测试方法论去测 25 岁的 PG 12.3, 在可串行化隔离级别下抓出了货真价实的 G2-item 反例,社区数周内修复。

三个故事指向同一个结论:考卷永远在补题。真正的资产是那台补题机器 —— 发现、复盘、修复、出新题的社区回路 —— 而不是考卷本身。 Hyrum 定律则指出:用户量足够大时,系统每一个可观测行为都会被人依赖;PostgreSQL 的 spec 就是 PostgreSQL,而测试只枚举得了已知行为。

这时候通常会有人祭出 SQLite:小团队,没有大社区,照样封神。看清楚它是怎么付账的。SQLite 靠的从来是极限测试 —— 闭源的 TH3 套件、100% MC/DC 覆盖、 测试代码约为库代码的六百倍——外加二十年、几十亿台设备滚出来的装机积分。真正的形式化证明在 DBMS 尺度上并不存在:seL4 验证一个一万行的内核,烧掉二十人年量级。 SQLite 的代码进了公有领域白送,验证资产闭源收钱。它没有绕开定律,它只是把社区尺度的验证内化成了私有资本。同一张账单,另一种付法。

最后送一个讽刺的注脚。PG 深知普通回归测试表达不了时序交错,专门造了 injection_points 故障注入框架来测这类东西。pgrust 把这个 contrib 模块也一并移植了。复印了一台自己还不会用的测谎仪。


五、扩展不是插件,是契约
#

还有一堵墙,比信任更硬,因为它是物理的。

PostgreSQL 的 C 扩展接口——fmgr 调用约定、hooks、共享内存、server headers、PGXS, 以及一大票事实上可见的全局符号——没有跨大版本稳定 ABI 的承诺,在现实里却是五百多个扩展与内核之间的源码契约,每个大版本都得追着适配。

Rust 重写者站在这份契约面前没有免费午餐:要么用 C-compatible shim 把旧接口接回来,吞下 unsafe 边界和长期兼容成本;要么逐个迁移扩展,接受生态断裂。所谓折中方案,只是把这两笔账按扩展切开,并不会让账单消失。

PG 的扩展宇宙有多大?pgvector 是里面比较好啃的,万行上下,谁都能翻。PostGIS 不行。GEOS、PROJ、GDAL 可以继续走 FFI,不必重写;真正要命的是 PostGIS 自己与 PG 的类型系统、内存管理、GiST、planner 和 hooks 咬得太深。语言可以换,这条边界不会凭空消失。

而没有 PostGIS,GIS 用户看都不会看你一眼——空间能力不是长尾需求,是标配。pgrust 目前移植了十二个 contrib 模块;我在 pgext.cloud 上编目在案的 PG 扩展是五百多个。十二比五百,这就是契约的重量。

不过,把话说到根上。AI 移动的是劳动供给曲线:写码的工时正在归零。但信任的公式一个字没变——装机量乘以风险敞口,对日历时间积分。工时可以压缩,日历时不能。

今天靠着 AI,一个人可以 13 天翻完 PG 内核,过几个月,把 PostGIS,或者整个 PG 扩展生态与依赖都翻译一遍,也未尝不可。所有押注在成本上的反对意见,保质期也许只有一个模型代际。站得住的问题只有一个:翻完之后,你手里握着的是什么?

答案是:240 万行没有任何人类通读过的代码,零验证积分,以及对每一个上游项目的永久追赶义务。

六、成本在通缩,信任不会
#

“完全兼容 PG”能继承多少信任?这事有现成的例子:

有担保人无担保人
保持兼容Aurora:信任成功转移,数十亿美元量级的年收入pgrust:转移率趋近于零
放弃兼容openGauss:退守特许市场,靠采购信任续命无名 fork:坟场

兼容性转移的是“预期行为”,担保人转移的是“出事有人赔半夜有人接电话”。信任是两者的乘积,缺一项就是乘零。 Aurora 兼容 PG 且背后站着 AWS 的可受罚性,于是通吃;而开源世界里最成功的 PG fork 是 Greenplum, 它在 2024 年被 Broadcom 停止公开开发并归档——冠军的原厂下场尚且如此。社区后来接过 Greenplum 7 的代码线,另起 Apache Cloudberry 续命,也恰好说明:担保一断,名字、治理和信用都得重新攒。

这张表里还藏着一个兼容悖论:fork 的存在理由要求分歧——不改,你图什么;信任的继承要求趋同——越像,才继承得越多。**一个 fork 的价值主张和它的信任来源,天然互相抵消。**pgrust 路线图上的每一个卖点——线程化、无 vacuum 存储、列存——都在亲手切断自己的继承权。

它越成功地成为自己,就越彻底地不是 PostgreSQL。

有人真金白银走过这条路,验尸报告是现成的。openGauss 从第一天起就是线程模型——pgrust 引以为傲的头号架构改造,人家早就交卷了——代价之一就是扩展生态的断绝。

openGauss 没有可以原样装上的上游 PostGIS,它的 GIS 能力靠超图领养的 Yukon(禹贡):2020 年 9 月启动 PostGIS 适配,2022 年 6 月才正式发布。一家专业 GIS 大厂,光“让 PostGIS 跑起来”就磨了近两年。现状呢? Yukon 最新文档已经到了 2.2,但 openGauss 适配线仍标作 Yukon 2.0–2.1、PostGIS 3.2.2;上游 PostGIS 稳定版已经到了 3.6.4。

官方版本矩阵老老实实列着:topology 和 mobilitydb 在 openGauss 一栏仍是空白,而且每个内核版本都要单独适配一轮。华为级的工程资源,加上国家级采购的需求拉动,最终买回来的是一份内核向前跑、GIS 适配在后面按版本追债的残卷。

这份价目表也顺带回答了一个国产数据库 “自研内核” 的问题。成本那条曲线,AI 会替你往下压;然而,信任和契约这两条,它一根指头都碰不了。做帕累托改进 —— 扩展、发行版、工具链,在不动根基的前提下做增量价值,做加法——才是真正的活路。

老冯自己就坐在这一层,坐了五年。Pigsty 的构建、打包、整条工具链全部开源,没有一行私有代码。 任何大厂分几个人手就能 fork 我,但 fork 带不走的那部分——五年积累的信任、编目、供应链——恰好是真正的核心。我敢把一切摊开,是因为我很清楚护城河从来不在代码里。


七、这场实验的正确遗产
#

说到这里,说说好的一面,这个实验本身值得一个体面的归宿。

pgrust 不该被当成产品 ,它自己也没这么要求过 —— 它该被当成一台测量仪器。它实测出了一个此前无人知道精确读数的量:PostgreSQL 三十年的知识里,有多少被固化进了考卷。满分是刻度的一端;接下来,它在真实负载下每踩中一个原版 PG 不会踩的坑,就等于测出了一条考卷没有覆盖的隐性不变量。 它的失败清单会比它的成功更有价值,而且这份价值天然归属上游 —— 每一个坑,都是一道可以回流 PostgreSQL 测试套件的新考题。

可惜代码不能直接回去:pgrust 选了 AGPL-3.0;除非作者另行授权,PostgreSQL 上游不能把这套 AGPL 代码直接并回 PostgreSQL License 主树。 “实验成果反哺社区”这条路,被自己的 license 焊死了一半 —— 发现能回流,代码不能直接抄。

比看着它翻车更值得做的事,其实已经摆在桌面上。PG 三十年修过的坑,大量属于“修了,但没留下考题”——时序型、平台型的 bug 尤其如此,修复的因果散落在邮件列表和 commit message 里,老兵退役一批,就带走一批。让 AI 干这个才是正途:

去考古三十年的 pgsql-hackers,把口耳相传的伤疤铸成回归测试和 isolation spec,把只可意会的经验转写成可以执行的考题。我在《开源的业力》里写过:agent 时代最有价值的社区贡献是一个可复现的失败,修复已近乎免费,稀缺的是复现,PR 的继任者是 failing test

从零重写是把三十年的默会知识扬掉;这个方向,是把它写进考卷,传给下一个三十年。


尾声:考卷可以复印,阅卷人不能
#

回到标题党们的问题:AI 重写了 PostgreSQL,然后呢?

然后我们得到了一次昂贵而诚实的测量:代码文本已经薄到 13 天可以翻译 240 万行,而三十年的信任,一点儿都没有随之转移。

有意思的是,项目作者比他的围观者清醒得多 —— 他亲手停掉了从零重写,保留 PG 的行为做锚、PG 的考卷做 oracle,他知道自己在翻译什么。

提交历史里有个细节我很喜欢。git 作者一栏里,Claude Fable 5 规规矩矩署了 832 个名——一个开始在履历系统里拥有名字、积累提交记录的 agent。《开源的业力》结尾预言过,市场将强制 AI 个体化,因为信用需要账户。这 832 个署名,大概算得上最早的一批化石标本。

AI 压缩了工时,压缩不了日历。翻译搬得走文本,搬不走业力。

考卷可以复印,阅卷人不能。


参考阅读

  • pgrust 仓库:https://github.com/malisper/pgrust
  • pgrust 系列博文(从零重写 → 67% → 100%):https://malisper.me/
  • HN 讨论(作者亲自答疑,含 c2rust 方法自述):https://news.ycombinator.com/item?id=48841676
  • Bun 的 Rust 翻译复盘:https://bun.com/blog/bun-in-rust
  • Andrew Kelley 的回应:https://andrewkelley.me/post/my-thoughts-bun-rust-rewrite.html
  • Jepsen 对 PostgreSQL 12.3 的分析:https://jepsen.io/analyses/postgresql-12.3
  • SQLite 测试方法(TH3 与 MC/DC):https://www.sqlite.org/testing.html
  • Yukon(禹贡)文档与已知限制:https://yukon.supermap.io/
  • 前篇:《开源的业力:当代码一文不值,信用从哪里来》:https://vonng.com/ai/oss-karma/

相关文章