来源:https://www.snowflake.com/en/blog/engineering/30-years-of-postgres-architecture-tom-lane/
Tom Lane 谈塑造 Postgres 三十年历程的架构决策
Elizabeth Garrett Christensen
我们正在庆祝 Postgres 的 30 周年。我们抽空与 Tom Lane 坐下来聊了聊,他是该项目的核心开发者之一,我们讨论了那些获得回报的架构赌注、早期的混乱,以及 Postgres 在云和 AI 时代的未来。
本次访谈也有视频版本。
PostgreSQL 正在庆祝其作为开源项目的 30 周年。我与 Tom Lane 坐下来交谈,他是核心团队成员,在其中的 25 年里担任提交者(committer)。我们讨论了在过去三十年中塑造该项目的技术和架构决策。
正如你将在本次访谈中看到的,Postgres 的架构和社区在过去三十年中一直保持稳定。虽然事情有所改进,功能有所完善,但项目总体上仍然是我们最初开始时的那个数据库项目。主要目标始终如一:不丢失数据、尽可能快地从崩溃中恢复,并通过扩展和新功能满足现代业务的需求。
开场
Elizabeth: 我知道在 30 年中,你大约有 25 年担任 Postgres 的核心提交者。对于不认识你的人来说,你能描述一下今天(2026 年)你在项目中的日常参与是什么样的吗?
Tom: 嗯,其实和 90 年代的样子没有太大区别。我的意思是,这一直是一个很大程度上由电子邮件驱动的项目。现在仍然如此。所以我想我大概花三分之一的时间阅读和撰写电子邮件,三分之一的时间审查别人的补丁,另外三分之一的时间处理我自己的补丁。显然每天变化很大,但这就是大致的流程。
Elizabeth: 你是 100% 只专注于核心 Postgres,对吗?除了参与核心项目之外,你没有其他活动?
Tom: 没错。
Elizabeth: 嗯,我有一些深入的技术问题,但为了让我们聊起来,先做几个你可以用很简短的回答来回答的问题,就当是娱乐一下。你的 IDE 是什么?你用什么进行核心开发工作?
Tom: Emacs。
Elizabeth: 你在工作时使用 Postgres 文档还是代码注释?还是说你脑子里已经装下了一切?
Tom: 不,我经常查阅文档。我更常查阅代码,因为代码注释中有大量信息从未进入文档。我脑子里大概知道所有东西在代码树中的位置,所以我经常能以比查文档快得多的速度找到东西。
进程 vs. 线程
Elizabeth: 当你连接到 Postgres 时,系统会专门为你生成一个完全独立的操作系统进程。你自己的查询执行器私有副本、你自己的内存空间,与其他连接隔离。像 MySQL、SQL Server 或 Oracle 这样的其他数据库使用线程,所有连接共享进程和内存空间。这是深入研究 Postgres 内部机制的人们常讨论的话题。Postgres 从这种隔离中获得了什么线程模型无法获得的东西,又有哪些权衡?
Tom: 嗯,我认为我们从中获得的主要是代码简单性。当你编写一段直线式代码时,你不必担心其他线程是否在中途弄乱你的数据结构。共享内存中有一些东西我们确实需要担心,但那实际上只是系统整体数据集很小的一部分。
在抗崩溃方面也有一些好处,因为如果某个特定会话进程发疯并崩溃了,我们不必担心它破坏了 postmaster 的某些状态------所以我们可以继续重启系统,并有信心我们仍然在处理良好的数据。
所以它肯定有优势,但也有劣势,我想我们稍后会谈到。有人正在研究转换为线程模型。但那涉及大量工作。我真的不知道它是否会成功。
图 1. Tom Lane 与 Postgres 的 30 年
Elizabeth: 你对那个讨论有特定的看法吗?你喜欢我们目前的模型,还是你现在如何看待这个问题?
Tom: 我没有特别参与正在进行的使系统线程化的工作;其他一些人在做大部分繁重的工作。显然,这将是另一组权衡和另一组优缺点,但我们当然应该推进这项工作,看看能否达到比现在更好的境地。
内存模型
Elizabeth: 因为每个连接是它自己的进程,每个后端有它自己的一块内存。然后我们有所有后端都能看到的共享内存------缓冲区缓存、锁表和事务相关的东西。你能更深入地谈谈共享区域与保持私有的部分,以及这如何塑造系统对其不同部分内存的处理方式?
Tom: 是的。嗯,首先------正如你刚才提到的------共享缓冲区缓存。来自普通表的所有数据,在处理时,都在那个共享缓存中。所以每个会话对任何特定页面都看到相同的视图,出于显而易见的原因,这对正确性至关重要。
另一方面,临时表位于每个会话本地的缓冲区中,这就是为什么你不能对另一个会话的临时表做任何操作。但作为回报,我们在处理临时表数据时不必担心锁定。所以有一些性能优势,也有一些劣势,例如你不能依赖后台清理(vacuuming)来清理你的临时表。
另一个值得一提的例子是,每个会话都有自己的缓存------它当前需要的目录数据的保留副本。这对我们真的很有帮助,因为它允许我们以相当直接的方式处理不同会话可能对目录内容有不同视图这一事实。例如,你可能对一个表有一个未提交的 DDL 修改------比如添加一列。在共享目录缓存中处理这个会相当困难。但在我们的世界里,拥有那个尚未提交的更改的会话可以在自己的缓存中看到它,而其他人都看不到。
图 2. Tom Lane 与 Postgres 的 30 年
Elizabeth: 这非常有趣。跟我说说临时表------它们是什么,如何创建。我在数据加载场景中使用它们更多,而在事务中使用得较少。
Tom: 我认为我们不允许你将临时表转换为非临时表,反之亦然。但它非常简单------你只需说 CREATE TEMP TABLE,其他方面与 CREATE TABLE 完全相同。表的内容在你的会话存续期间一直存在,除非你删除它。当你退出会话时,可能存在的任何内容都会被自动删除。它基本上只用于你在会话结束后不会关心的瞬态数据。
WAL 与崩溃恢复
Elizabeth: 关于 Postgres 有一件事让很多人感到惊讶:虽然你可以有很多进程并发写入数据,但每个 INSERT、UPDATE 和 DELETE 都会并行生成预写日志(WAL)记录。而且只有一个进程可以执行崩溃恢复并重放这些记录。你能谈谈底层的架构------恢复过程和预写日志如何工作,以及这对你设计 WAL 系统意味着什么?
图 3. Tom Lane 与 Postgres 的 30 年
Tom: 嗯,这基本上是为了减少提交事务之前必须发生的磁盘写入量。其思想是,任何时候你去更新表或索引或其他任何东西中的页面时,在你实际在共享缓冲区中进行该更改之前,你必须向预写日志发出一个记录,说明你即将做什么。
然后你去做。如果系统在该更改写入磁盘之前崩溃,那么在恢复期间,我们可以重放它并从 WAL 日志重新应用该更改。这样做的目的是,你不需要让待处理的写入可能分散在你的所有表和所有索引中,而是有一个必须被写出并提交的单一数据流。
一旦你知道 WAL 数据在磁盘上,你就可以安全地提交事务,即使共享缓冲区中可能还有一大堆其他数据尚未写出。所以这基本上都是为了让磁盘 I/O 系统更友好。
我们最终确实必须同步那些表写入,但我们直到检查点(checkpoint)时才做,而检查点不会太频繁地发生。而且它是一个后台操作,你的事务提交不会等待它发生。
图 4. Tom Lane 与 Postgres 的 30 年
Elizabeth: 我听到很多人调整检查点超时作为管理 I/O 的一种方式。
Tom: 是的。再说一次,那是一个我没有深入专业知识的实践问题。我知道它如何工作,但我不知道设置的最佳位置在哪里。
你提到重放只是一个单一进程这一点。我认为这基本上部分是因为没有人着手处理它,但也部分是因为希望尽可能保持该机制简单。我们希望确定系统会恢复。所以我们不希望那个重放中存在任何潜伏的 bug。也许它会在某个时候被并行化,但我认为没有人在积极研究这个。
连接扩展
Elizabeth: 我们一直在谈论每连接一进程。如果单个进程中出现某种问题,它会自行消亡,不会拖垮任何其他会话。这有很好的隔离性。但我生活在一个有很多繁忙应用、应用服务器集群、数千个连接都与单个 Postgres 数据库通信的世界里。社区主要通过像 PgBouncer 这样的外部连接池器解决了这个问题。你如何看待这个世界------我们有有益的崩溃隔离,但连接扩展带来开销?当前的连接池器方案是最好的方式吗,还是 Postgres 正在研究某种长期的架构变革?
图 5. Tom Lane 与 Postgres 的 30 年
Tom: 是的,这肯定正在被考虑。这里不为人知的秘密是,如果一个进程崩溃,我们反正会干掉其余所有进程,因为我们不完全确定那个进程在实际失败之前没有设法破坏共享内存中的任何东西。
所以实际发生的是,postmaster 杀死它所有的其他子进程,并在允许任何新子进程启动之前生成一个全新版本的共享内存。因此,从崩溃恢复的角度来看,我们真正需要做的就是把 postmaster 保持为一个独立的进程。我们可以让所有实际工作由一个大的进程内的线程来完成,从崩溃恢复的角度来看它是一样的。
我们为了达到那个目标必须解决的诀窍就像我之前暗示的那些------如果我们能支持更多的会话就好了,但困难在于每个会话都有一些目录缓存。在你于这些缓存中积累合理数量的数据之前,会话速度不会很快,因为每次它想发现某个新事实时,都必须去查目录。
正因为如此,一旦你有一个会话已经相当好地填充了它的缓存,它就准备好完成一些工作了。它有点像一个大型的重量级对象,你不想立即杀死它。所以这就是为什么人们选择了这种池化方案,你连续地重用同一个后端进程来处理属于不同应用线程的不同查询。
为了超越这一点,我们必须解决如何跨会话共享缓存的问题,而这些会话可能对相关数据实际是什么有不同的看法。人们正在研究这个。但这是一个相当棘手的问题。我不确定我们接近有解决方案了。
线程化与现代硬件
Elizabeth: 现在有如此大的服务器。在大型实例中看到 128 或 256 个 CPU 核心很常见。你认为线程化和现代硬件的最终目标或方向是什么?
Tom: 嗯,你当然可以启动一个有 100 或 200 个活动后端进程的系统,只要你内存足够,它就能相当好地工作,因为同样,每个会话需要相当多的工作内存。但如今的服务器如此巨大,这不是什么大问题。
如果你试图运行比那更多的会话,困扰你的往往是上下文切换时间。因为每个会话都有自己的内存映射,你必须将其加载到 CPU 缓存中。
切换到线程模型的希望是我们可以稍微减少那部分开销,因为线程都共享相同的地址空间。所以达到那个目标肯定很有趣,但我们需要一段时间。
是什么让 Postgres 成功
Elizabeth: 退一步说,你认为这些架构选择中,哪些真正让 Postgres 从一个相当小的学术数据库项目变成了市场上最流行的关系型数据库,从而产生了如此巨大的差异?
Tom: 我要指出的一点就是系统的相对简单性,这源于像没有尝试线程化这样的选择。这不是我们有意识选择的。当我们在 90 年代末最初使用该系统时,考虑使用线程根本不现实,因为它没有得到很好的标准化。我们感兴趣的每个平台的做法都略有不同。显然这在过去 20 年里已经改变了,但当时那是甚至考虑这个想法的一大障碍。但它确实为我们买来了大量的简单性,这意味着人们可以在没有太多背景知识的情况下进来为系统工作,这对我们帮助很大。
我想指出的另一件作为我们能做什么的重大阶跃变化的事情是:当我们从伯克利获得代码时,它根本没有预写日志。如果你崩溃了,你经常面临不得不从你拥有的任何备份重新初始化数据库的局面。所以我认为加入那个对我们的可靠性以及说服人们我们可以用于生产目的的能力产生了巨大差异。
MVCC 的权衡
Elizabeth: Postgres 使用多版本并发控制(MVCC)处理并发读写。当一行被更新时,Postgres 不会覆盖它。它在行头中写入带有事务元数据的新行副本到表中。读取者在写入发生时查看旧版本。你最终会得到旧的死行,由 VACUUM 清理。其他数据库工作方式不同。它们有某种撤销日志。你从架构上如何看待 MVCC?你觉得那是一个好的方法吗,还是有关于做不同事情的讨论?
图 6. Tom Lane 与 Postgres 的 30 年
Tom: 不,我认为它从根本上是一个好的设计。原因正是你必须做的那些维护工作确实被推到了后台进程中。它不会干扰你执行人们想要完成的实际工作的能力。
例如,使用基于撤销的系统,你必须回去重放那个撤销才能中止你的事务。所以只要你提交一切,那不是太大的代价。但你仍然有如何在不阻塞人们的情况下呈现一致数据快照的问题。
所以我认为这是一个好的设计,因为它将大量维护工作推入后台进程。显然我们在 vacuum 上花了大量工程努力,并将继续花大量工程努力。但我认为如果我们没有它,我们只是需要在其他地方以不同的方式解决同样的问题。
Elizabeth: 我认为 Postgres 19 将获得并行 vacuum,对吗?
Tom: 那是新的。我没有密切关注那个。但是的,例如 Melanie 在 vacuum 上做了大量工作。
但我记得大约在 2000 年的一次对话------有个人在贸易展上走到我面前,他显然是一个非常非常资深的 Oracle 专家。他对我说:"你们做对了。我们做错了。"我总是喜欢听到这个。
也许他是在引导我,谁知道呢?但是的,我对这个方向并不不满意。这就是我们拥有的,它工作得相当好。我们知道如何继续改进它。
Elizabeth: 我认为 autovacuum 也很巨大------不依赖人们设置自己的 vacuum 进程。Postgres 现在几乎为你完成所有这些,除非你有一个非常大的数据库或什么不寻常的东西。
Tom: 是的,那是另一个我们做了大量工作来调整 autovacuum 启发式以知道何时 vacuum 的领域。那项工作仍在继续。但是的,我认为那总体上相当成功。
Postgres 查询规划器
Elizabeth: 我知道你自己在查询规划器上做了不少工作。当你编写一个 SQL 查询时,Postgres 查询规划器会考虑许多不同的执行策略------它决定是扫描整个表还是使用索引,是想要嵌套循环、哈希连接还是合并连接,连接中表的顺序。有很多内部统计信息和成本模型来选择正确的查询计划。这是让 Postgres 成为 Postgres 的原因之一。你能向人们大致介绍一下查询规划器如何工作,是什么让它复杂,以及你在哪里看到未来的工程工作?
Tom: 嗯,正如你所说,基本上它考虑一大堆不同的执行策略,并试图选择根据其成本模型最便宜的那个。所以第一个漏洞当然是成本模型并不总是对应现实。然后第二个漏洞是,一旦你超过相当少的连接表数量,可能的执行计划数量就会呈指数增长。
图 7. Tom Lane 与 Postgres 的 30 年
所以在那个点上,我们必须回退到启发式地搜索计划空间的一部分------这有时导致我们找不到好的计划。所以这意味着我们总是对改进成本模型感兴趣,我们总是寻找减少规划器执行时间的方法。而这些目标有点冲突。所以基本上涉及大量复杂的工程权衡------在合理的时间内获得好的查询计划。而这种复杂性正是我觉得它有趣的地方。
Elizabeth: 你在近期或长期视野中有什么关于查询规划器重大更新的东西,还是更小的迭代工作?
Tom: 我目前没有在其中做大的事情。其他一些人已经站出来了------例如 David Rowley、Richard Guo------正在那个领域做重要的事情,那很好。但是的,它仍然是我的初恋,如果我有机会研究它,我会的。
C 与内存上下文
Elizabeth: Postgres 大约有 150 万行 C 代码------一个巨大的代码库,不是独立的模块。该项目不使用标准 C 模式,而是使用内存上下文(memory context),你分配到一个与查询或事务相关联的命名上下文树中,当那个工作单元完成时,整个树一起被释放。工程界有很多关于 Rust 和内存安全语言的讨论。你如何看待内存上下文模式作为编译器强制内存安全的替代方案?你认为 Postgres 会继续作为一个大的 C 项目,还是有兴趣重写部分或分解它?
Tom: 我没有看到很多重写它的兴趣。我们大约 20 年前有过一些讨论,比如是否用 C++ 重写它。我们稍微探索了一下,得出结论成本效益根本不值得。我不确定今天用现有的东西会更好。
关于内存上下文的问题------需要理解的是,我们在整个系统中有不同生命周期的不同上下文。有些存活整个会话的生命周期。有些存活一个查询的时间。有些在查询中处理的每一行都被重置。
游戏规则通常是尝试在你能做到的最短生命周期上下文中分配东西。假设你能做到这一点,你基本上可以不再担心内存泄漏,因为你可能忘记清理的任何东西都会在合理的时间内自动消失。
事实上,在我们的代码中逐个释放东西有点反模式,因为上下文清理比单独释放该上下文中可能存在的每个东西要高效得多------而且也更健壮,因为如果你忘记专门释放某个东西,它仍然会被清理。
这种心态的缺点是,如果你必须在长生命周期上下文中工作,忘记释放某个东西就确实重要了。我们经常将那种心态带到不适用它的地方,然后我们就有一个必须修复的内存泄漏 bug。所以它肯定不是没有缺点,但它确实非常契合我们需要做的事情。
我想我发明了这个概念,或者其中的大部分。所以我可能有偏见。但我认为它工作得很好。
除了在真正重要的地方出现泄漏的问题之外,还有在一个上下文中构建一个数据结构,而该结构有指向另一个更短生命周期上下文中的某个其他数据结构的指针的问题。然后你就有悬空指针问题。所以肯定不全是美好,但它非常契合我们的问题,我并不真的相信语言强加的内存安全模型会同样适用于我们。我没有花时间实际研究那个,所以我不能肯定地说------但我对此持怀疑态度。
扩展
Elizabeth: 我想谈谈 Postgres 扩展的世界。现在开发者使用 Postgres 做所有事情的趋势非常巨大------"就用 Postgres。"你可以把它用作键值存储。你可以用 LISTEN/NOTIFY 做消息队列。你可以把它变成作业调度器。你可以把它变成文档数据库。你可以做大量的事情。而宣传是为什么要运行五个不同的数据系统,当一个 Postgres 可以做所有事情时。作为一个专注于这个核心数据库的人,你喜欢这种多功能性吗?你觉得它令人兴奋,还是担心人们把 Postgres 推得超出它被设计用于的范围?
Tom: 嗯,可扩展性从一开始就是项目思维的一部分。伯克利的人构建它就是为了让你可以添加新的数据类型。他们也有你可以添加新的索引访问方法、构建新型索引的想法。
从那时起,我们有点接受了这一点并加以发展,添加了其他扩展系统的方式。所以例如,如果一个提议的功能只适用于核心数据类型,并且没有办法扩展它以适用于扩展数据类型,我们可能不会以那种形式接受它。我们会说,回去思考一下这如何可以被扩展,然后再回来。
我认为这在吸引想要围绕和基于核心 Postgres 构建东西的人方面为我们服务得非常好。所以我认为拥有那种思维是项目成功的重要组成部分。所以是的,我绝对属于说这是个好主意的阵营。当然有些任务关系型数据库不适合,但人们经常发现我们足够好。然后这节省了他们必须与某个其他工具集集成------在很多方面都很好。
所以例如,你提到 LISTEN/NOTIFY------它是一个好的简单信号机制,但扩展性不太好。所以如果你必须传递大量消息,你将不得不去找别的东西。但对很多应用来说它足够好。
解析器可扩展性与扩展的极限
Elizabeth: 让我们谈谈扩展在 Postgres 本身中如何工作。你可以添加新的数据类型。你可以做新的索引类型、新的运算符。你甚至可以把过程语言放进 Postgres。你可以在不触及核心 Postgres 引擎的情况下做到这一点并构建扩展。但据我所知,扩展不能修改 SQL 解析器。所以如果你想要一个新的关键字、一个新的子句,那是对核心 Postgres 的补丁。而将补丁进入核心 Postgres 是一个相当大的项目------可能甚至是主要版本发布中的多年审查周期。像 pgvector 这样的 AI 嵌入扩展,是通过现有 SQL 语法做所有事情。人们如何看待这条线?有关于使其中一些解析器可扩展的讨论吗?
Tom: 是的。所以这基本上回到我们使用 Flex 和 Bison 构建解析器这一事实。那些工具读入语法的静态描述,构建一些解析表,然后这些被编译进服务器。这就是它。你不能动态改变它。
原则上我不反对可扩展解析器。事实上,在 Postgres 甚至还不存在之前的 70 年代,我就在研究那样的系统。但从那个经验中我知道可扩展解析器比你想象的更难构建。Bison 的伟大之处在于,如果你的语法有歧义,它会告诉你并让你修复它。然后就没有运行时意外,比如,你实际上无法获得那个行为,因为它被某个其他与之有歧义的语法掩盖了。
所以如果我们确实找到另一个我们想看的可扩展工具,我会问一些尖锐的问题,关于我们如何能获得类似的正确性保证。
关于 Bison 的另一件事是它就在那里------文档齐全、调试良好。它是免费的。它在任何平台上都随时可用。我不知道有任何竞争工具具有这些属性。但正如你所说,这肯定是可扩展性故事失败的一个地方。所以如果我们能找到更好的东西,我会全力支持。
Tom Lane 的 Postgres 之旅
Elizabeth: 今天和你聊天之前我做了一些研究,看起来互联网认为你开始研究 Postgres 是因为你需要一个数据库来存储股票交易信息,你开始是一个用户和 bug 报告者,然后提交了一些补丁,然后成为核心提交者。如果那个故事不真实,请随时纠正。那个演变是如何发生的?当你第一次看到这个项目时,你知道你会花 30 年研究它吗?
Tom: 不。我完全不知道。是的,故事相当准确。我需要一个数据库,我们不想为 Oracle 付费。当时两个合理的选择是 Postgres 和 MySQL,我看了 MySQL 的代码库,决定我不想和它有半点关系。
Elizabeth: 我稍后得回到那个话题。
Tom: 我看了 Postgres 的代码库,它看起来结构好得多。所以我们开始使用它,立即遇到一些我们不得不发送修复的 bug,它就从那里发展起来了。
到那时为止,我对数据库一无所知。当我还是研究生时,我的教授们根本不在乎数据库。所以我很感兴趣地发现底层实际上有有趣的问题,然后就被吸引进去做越来越多的事情。
Elizabeth: 哦,那太有趣了。你是在项目从 UC Berkeley 作为开源项目出来几年后开始的。当你第一次进入这个项目时,那时的 Postgres 是什么样的?有你知道需要改变的重大东西吗?
Tom: 系统的骨架很好。如果不是那样,我们永远不会有什么成就。但是的,我们有大量的小 bug 需要识别和修复。那个时期花了几年才真正达到我们可以说系统相当无 bug 的地步。
就主要功能而言,我认为那些年里我觉得唯一缺失的是崩溃恢复。我们已经谈过那个,预写日志机制就是处理那个的。否则,在我参与整个过程中一直存在的另一个主题是从它那里获得越来越多的性能。
Elizabeth: 当然。是的,但它一定相当高效,所以你一定用过它。你在早期使用 Postgres 与你正在做的项目一起吗?
Tom: 是的。我们实际上确实用它做了一定量的股票交易。我们有一些市场模型,它们一直工作直到停止工作。在那之后我们退出了那个业务。
为什么 Postgres 存活了 30 年
Elizabeth: 过去 30 年数据库领域发生了很多事情。那个时代有很多其他流行的数据库已经消失或只是被吸收到其他项目中。对于任何软件项目来说,30 年能像 Postgres 一样流行是相当老的。你认为那些早期决策中哪一个让 Postgres 作为一个独立项目存活了这么久?
Tom: 在我看来,毫无疑问是伯克利放在它上面的宽松许可条款,允许人们以他们想要的任何方式使用它,甚至在他们想要的时候在它上面开始专有分支。很多人这样做了。但问题是,因为它完全合法,每个人都理解这一点,他们仍然与社区项目保持联系,并回馈部分工作,因为他们宁愿有一个坚实的基础来构建。
人们会在做专有东西和做社区项目之间来回切换。我认为早期完成的很多工作基本上是由那种模式资助的,你在社区 Postgres 之上销售某些东西。
我想你可以看的另一个类似年代的项目是 Linux。他们走了不同的方向。显然他们选择了 GPL,这有另一组权衡,但同样,它是人们知道如何合作的东西,它没有阻止人们为项目做贡献。
Elizabeth: 我同意,我经常谈论 Postgres,我确实指出许可证,因为我认为它是一件大事。这么多人不仅能够为它做贡献,并在它上面建立整个业务。我认为虽然 Linux 和 Postgres 有略微不同的运营模式和许可证,但两者一路互相帮助。Linux 在过去 30 年里没有去任何地方。而它作为操作系统的流行以及 Postgres 在那个世界中工作得如此之好也是一个因素。
Elizabeth: 你参与了任何许可事务吗?据我所知,Postgres 有自己的许可证,PostgreSQL 许可证,我认为它和 FreeBSD 许可证非常相似。
Tom: 是的,在我们看来------嗯,实际上研究这类事情的人告诉我它更像是 MIT 许可证。和 BSD 并不真的相同,尽管它来自伯克利。但无论如何,作为非律师,我对它的解释是你可以用这些代码做你想做的任何事情,只要你不起诉我们。
Elizabeth: 我认为像亚马逊、谷歌和微软这样的大型云提供商能够用 Postgres 建立整个业务,并作为服务销售 Postgres......我认为这也帮助了它的流行,特别是在我们现在生活的云世界中。那里没有规则。所以这么多人愿意托管它并帮助人们付费运行它这一事实也帮助了它的流行。
Tom 最喜欢和最不喜欢的版本和功能
Elizabeth: 你最喜欢的 Postgres 版本是什么?
Tom: 那是个难题。通常我最喜欢的版本是最新的。回顾我们刚才的对话,我会说作为一个高点可能是 8.0,那是我们加入 WAL 日志恢复的地方,原因我们提到了。那是向成为严肃数据库而不是玩物迈出的巨大一步。不过我可以反过来,告诉你哪个肯定是我最不喜欢的:版本 13,它绝对充满了 bug。我们在那之后几年一直在修复它的 bug。它至今是我们最有问题的版本。
Elizabeth: 13 中有什么特别有问题的功能吗?
Tom: 幸好大部分细节都记不清了。
Elizabeth: 你有一个你编写并非常自豪的特定功能吗?
Tom: 我把我在 Postgres 的工作视为大量不太大的单个部分的大量积累。我可以挑出这个或那个,但可能它们单独听起来都不会那么大。
Elizabeth: 如果你明天可以删除 Postgres 中的一个功能,没有向后兼容性的顾虑?
Tom: 我不喜欢我们做分区的方式。我不知道如何做得更好,但它很乱。
Tom 在 Postgres 之前的工作
Elizabeth: 我知道一些你在加入 Postgres 项目之前的历史。我想你做过 JPEG------图像规范方面的工作。互联网认为你在 libjpeg 上做了一些工作,那是火星毅力号相机工作的一部分。跟我说说那个以及那些东西如何影响你在 Postgres 中的工作。
Tom: 所以我和 JPEG 规范的编写没有任何关系。但它出来了,可能有大约十几个人对此感兴趣并说,让我们坐下来写一个它的开源实现,我们这样做了,那就是 libjpeg。我------一开始有这一阵活动,可能有大约十几个人参与。之后,它有点进入维护模式。我担任它的主要维护者大约五年,这就是为什么我的名字比其他人的更多地出现在上面。
当我参与 Postgres 时,那变成了吸走我所有时间的东西。所以我停止了在 libjpeg 上的工作。我很高兴其他人接手并继续下去,在我忽视它足够长时间后他们最终这样做了。
我确实知道毅力号上的工程相机使用 libjpeg,因为 Joe Conway 发现一篇学术论文这样说。他们从未与我直接联系过。
Elizabeth: 开放图像规范和数据库之间有交叉吗?
Tom: 没有直接关系,但它确实影响了我对软件许可证之类事情的思考。我认为 JPEG 今天无处不在这一事实,25% 是因为它是一个真正伟大的标准,让你能制作出比之前同等质量小约 10 倍的图像文件,75% 是因为有一个任何人都可以使用的免费实现。没有那个,它不会被放入早期网络浏览器,你不会在网上到处看到它。
我们在那件事上做了正确的决定。然后当我来到 Postgres 时,它有一个非常宽松的许可证这一事实是吸引我的重要部分。
Elizabeth: 你是如何对这个开源理念感兴趣的?显然你对协作式开源软件项目有热情。你是在大学里遇到这个的吗?你什么时候开始对这个理念感兴趣的?
Tom: 我是在 80 年代作为研究生时接触到的。如果你在学术环境中,显然到处都有软件漂浮,没有人特别想主张版权------他们宁愿分享、改进和使用。所以我在那个时候接触到了那种思维。
我特别参与的原因是我刚完成我的博士学位,那主要是由美国纳税人支付的,我觉得我需要做点什么来回报整个世界。所以我在寻找一个我可以奉献给世界的开源项目,稍微偿还我对社会的债务。然后 libjpeg 出现了,我说,嗯,这看起来很有趣。我会参与这个。
Elizabeth: 你的博士论文是关于什么的?
Tom: 软件架构。论文标题实际上还有几个词,但基本上就是关于那个的。
Postgres 治理
Elizabeth: 我想谈谈项目运作方式和治理模型。它有点独特。大多数这种规模和级别的开源项目运作方式略有不同。它们可能有一个正式的基金会,可能有一个董事会,可能有一些企业赞助商。我想到的是 Apache 基金会、Linux 基金会、Python 软件基金会、Kubernetes 的 CNCF 这样的组织。Postgres 并不真的那样运作。据我所知,PostgreSQL 开发组甚至不是一个正式的法律实体。它比外面其他一些更大的项目更非正式一些。它更自我选择。你有一个核心团队,自我选择的提交者,真的主要是基于电子邮件的。你甚至不能提交拉取请求。Postgres 代码在 Git 中,但那只是一个镜像。一切通过电子邮件发生。你如何看待这种治理模型?
Tom: 老实说,我不太知道我们是如何设法让它运作的。它在某种程度上是被项目初始条件强加的。我们有伯克利刚扔过墙来的这一大块代码。我们不拥有它。我们不能对许可证做更改。我们讨论过那个,最终决定我们根本没有权利对许可证做更改,因为那时我们不是代码的原始或主要作者。
所以你被困在许可证上。我们有一堆贡献者,他们中没有人对彼此负责;他们都为不同的人工作。所以任何真正强大的治理模型都不会奏效。人们会走开。
所以我们从未有过任何正式的东西。一开始,核心团队是拥有和运行我们 CVS 服务器的人,因此拥有发放或不发放提交权限的权利。但那没有持续太久。不久之后我们就有了一个独立的基础设施团队。所以现在核心委员会没有任何正式权力。人们听我们的话是因为他们一直如此。但我不太确定如果我们真的陷入一场关于项目应该如何运行的严重激烈争斗,会发生什么。但不知何故它已经维持了 30 年,我不太理解它是如何形成的。
Elizabeth: 我认为参与项目的大多数人都对 Postgres 本身相当投入。如果你不是想让项目更好,你不会写补丁。它移动得并不快。大补丁需要数年才能进入,甚至小补丁也可能需要数年。但我认为在某些方面这创造了项目的稳定性,因为它不会去做下一个最新的东西,或基于单个人或单个公司的兴趣重写部分内容。你从这种"我们都同意"的模型中获得了大量稳定性。
Tom: 我认为这在某种程度上来讲是这个领域的特性。人们希望他们的数据库是无聊的。当他们把数据放进去时,他们想知道明天能够把数据取出来。而需求并没有移动得那么快。每五到十年,SQL 委员会会出来一个新版本的标准,其中有一些新东西,我们看看它,也许我们觉得想实现它,也许不想。但没有真正的东西驱使我们匆忙做出改变。对于我们在做的事情,那是好的。
Postgres 的未来
Elizabeth: 你认为 Postgres 接下来走向哪里?我们一直在谈论治理模型,这个规模的一些项目可能有路线图或指导委员会。Postgres 并不真的有那个。我们谈了一些线程化。还有其他可能进入核心 Postgres 的更大转变吗?很多人问像备份或高可用性这样的事情。你在考虑在 Postgres 中做更多这些吗?
Tom: 正如我所说,没有项目路线图。再次,这源于这样一个事实:肯定在项目的早期,没有人能告诉别人该做什么。如果你想完成任何事情,你必须说服人们你的想法是好主意,然后也许他们会研究它并帮助你。我们仍然在那个基础上运作。显然,现在有些人受雇于可以告诉他们做什么的公司,但仍然是,如果他们想看到它进入社区代码,他们必须说服所有其他人。
我们已经谈过线程化以及想要它的基本上基于性能的原因。我认为已经持续一段时间的另一个主题是人们希望有能力使用列组织表,而不是我们目前支持的传统的行组织表。我们已经有了表访问方法 API 的概念,但它还不够通用,不允许有人放入列组织表。但我认为人们仍然对那个概念非常感兴趣。他们会继续朝那个方向推进。也许我们会达到那里。
除此之外,我个人不赞成将那些作为扩展工作得很好的东西卷入核心。我们只有非常有限的工程人力在处理核心代码。使它越来越大只会让我们越来越捉襟见肘。我通常属于那个阵营,说如果它能作为扩展合理地工作,就让它保持为扩展。
AI 与 Postgres 社区
Elizabeth: 在这次访谈的大部分时间里,我没有谈论 AI,做得相当好。如果我能在一场晚宴上不谈论 AI,我会感到非常自豪。但显然我好奇你的世界里 AI 正在发生什么。你在采用任何 AI 编码工具或审查工具吗?
Tom: 个人而言,我用 Claude Code 做过几件小事,但我不能说我已经以主要方式深入其中。
整个社区仍在讨论我们是否想接受很大程度上由 AI 生成的提交。我们实际上几周前刚有一个研讨会,我们二十几个人聚在一起亲自讨论这些东西。我认为那个小组的共识是,我们仍然希望有一个人为进入代码库的每一件事背书,并能够解释其中的每一个决定。即使它部分是 AI 编写的。那还不是正式的项目政策。但我认为我们很快会在更广泛的社区中进行这些讨论,并试图统一某种政策。
已经明确影响我们工作流程的一件事是我们收到大量 AI 生成的 bug 报告和安全报告。很多是现在幕后正在发生的事情。这有点问题,因为当然很多是需要修复的有效 bug。但其中也有相当多的垃圾,因为工具不理解基本架构概念。希望那会改善。或者至少我们能弄清楚如何更有效地过滤那些东西。
Elizabeth: 我知道邮件列表目前有一点封锁。所以据我所知,没有机器人发布到邮件列表,但也许有,而我没有听说。你听说过非人类发布到黑客列表(代码工作和人们交流的地方)吗?
Tom: 我没有看到任何那样可识别的东西。肯定有增加的人只是拿 AI 生成的报告直接作为 bug 报告发布,那种事情。但我没有看到任何在我看来像机器人实际订阅了邮件列表的东西。也许我只是错过了。
Tom 的开发环境
Elizabeth: 跟我说说你的本地开发设置?
Tom: 我大部分工作在 Linux 服务器上使用 Emacs 和命令行工具。我实际坐着打字的是一个 Mac 笔记本电脑,通过 SSH 和 X11 连接到服务器。这基本上是我多年前进入的设置,因为我有巨大的工效学问题。我需要一些我可以把手放在膝盖上的东西。所以笔记本电脑放在我的膝盖上------那是我的手所在的地方------我看着面前一个足够大的独立屏幕来工作。
Elizabeth: 什么 Linux 发行版?
Tom: 我多年前为 Red Hat 工作,所以我仍然主要使用 RHEL。服务器现在在 RHEL 10 上,我有几台 Fedora 机器散落在各处。
Elizabeth: 你选了新的那些中的一个吗,Alma Linux,CentOS 之后的新 Linux 发行版?
Tom: 不,不。我实际上向 Red Hat 付费订阅。我仍然相信他们在做的事情,我认为他们需要被支持。
结束
Elizabeth: 你接下来有什么打算?除了 Postgres 生活之外你有计划吗?
Tom: 不。不真的。我想我会继续研究 Postgres,直到要么我决定我对项目感到无聊,要么我意识到我过时了。我不知道那些事情何时或是否会发生,但现在我很满足于继续做我正在做的事情。
Elizabeth: 非常感谢你今天和我在一起,Tom。我真的很感激。我在几家不同的公司与你合作过,我对这个项目有特殊的感情。非常感谢你今天加入我以及你在项目上所做的所有工作。
Tom: 嗯,非常感谢你邀请我。很有趣。
由 Snowflake 呈现。
了解更多关于作者
Elizabeth Garrett Christensen
开发者布道师