PostgreSQL正在考虑将基于进程的模型迁移到线程模型


PostgreSQL 在大型系统上的扩展性不佳,主要是因为基于进程的模型都消耗了资源。
并非所有数据库都有这个问题,如果不进行某种重大的架构更改,PostgreSQL 就无法停止这个问题。

PostgreSQL 数据库系统,它的历史可以追溯到1986 年。对具有如此悠久历史的大型代码库进行根本性更改从来都不是一件容易的事。随着根本性变化的发生,使 PostgreSQL 摆脱面向过程的模型并不是一件小事,但该项目正在认真考虑这一变化。

PostgreSQL 实例作为一大组协作进程运行,其中每个连接的客户端都有一个进程。这些进程使用复杂的库通过多个共享内存区域进行通信,该库允许在并非所有进程都具有映射到同一地址的相同内存的设置中创建复杂的数据结构。

这种模式多年来一直很好地服务于该项目,但在该项目的历史上,世界发生了很大的变化。因此,PostgreSQL 开发人员越来越认为可能是时候做出改变了。

6 月初,Heikki Linnakangas 似乎在跟进一些现场会议讨论,发布了一项将 PostgreSQL 迁移到线程模型的 提案。
该消息快速概述了采取这一举措所涉及的一些挑战,并以低调的方式承认这一转变“肯定无法在一个版本中完全完成”。

正如安德烈斯·弗罗因德所说
我认为我们开始遇到与进程模型相关的相当多的限制,特别是在更大的机器上。
跨进程上下文切换的开销本质上比同一进程中的线程之间的切换要高——而且我怀疑这种开销会继续增加。
一旦拥有大量连接,我们最终会在 TLB 未命中中花费“大量”时间,这是进程模型固有的,因为您无法跨进程共享 TLB。

流程模型增加了开发成本,迫使项目维护大量重复代码,包括在单个地址空间中不需要的几种内存管理机制。

如果从进程模型切换到线程模型:可以在线程之间更有效地共享状态,因为它们都在同一地址空间中运行。

将 PostgreSQL 服务器的核心移至单个地址空间肯定会带来许多挑战。最大的一个似乎是服务器“广泛且常常无偿地使用全局变量”。
当每个服务器进程都有自己的集合时,全局变量工作得很好,但当使用线程时,这种方法显然会失效。
目前 PostgreSQL 服务器使用了大约 2,000 个这样的全局变量。

解决这个问题的几种方法:

  • 一种是将所有全局变量拉入一个大的“会话状态”结构,该结构将是线程本地的。然而,当人们考虑尝试创建和维护一个 2,000 名成员的结构时,这个想法很快就失去了吸引力,因此该项目不太可能走这条路。
  • 另一种方法是简单地将所有全局变量放入线程本地存储中,这是一种简单且有效的方法,但大量使用线程本地存储会带来性能损失,从而首先降低切换到线程的好处。

专门标记全局变量(将它们放入线程本地存储等)本身就是一个有益的项目,因为这将是减少全局变量使用的良好第一步。即使永远不会切换到线程,这种努力也会得到回报。

虽然讨论的结果表明大多数 PostgreSQL 开发人员认为这种变化在抽象上是好的,但显然也有人担心它在实践中如何运作。目前还没有人站出来表示他们愿意投入时间来推动这一努力。如果没有这个关键因素,在任何可预见的未来都不会转向线程。