PROD欧洲主权BaaS平台打开仪表板 →

性能 · 9 最小读取值

Postgres max_connections 没有池化器

Affane Daylami · Fondateur · 2026年6月6日

返回博客

如果没有在服务器前面进行池化,max_connections 应该同时覆盖每个打开的客户端连接,而不是 Postgres 可以有效并行处理的请求数量。混淆这两个数字是错误设置 max_connections 的最常见原因:太低而无法吸收负载,或者太高而无法满足实际可用内存的需要。

该英文文本是根据法文原文自动生成的,尚未经过审查。
该页面已自动翻译。英文版具有权威性。

本文给出了 PostgreSQL wiki 发布的计算硬件理想并发的公式(生态系统中引用最多的 连接池大小计算公式),解释了为什么每个连接的成本比应用程序线程高,然后详细介绍了设置 max_connections 的过程,无需猜测。我们的 基准测试方法 记录了本博客上用于任何性能声明的测量协议。

要点

  • 如果没有池, max_connections 应该覆盖 所有 并发客户端连接,而不仅仅是 Postgres 可以有效并行处理的那些连接。
  • PostgreSQL wiki 参考公式:理想活跃并发数 = (物理核心数 × 2) + 高效磁盘数。通过测量验证的起点,而不是硬性限制。
  • max_connections 是一个 postmaster 上下文参数:更改它需要完全重新启动服务器,而不是简单的重新加载。
  • 每个 Postgres 连接都是一个单独的系统进程,而不是轻量级线程:这就是连接数量一增加就会造成开销的原因。
  • 在代码中验证:在其专用的 Postgres 集群上,Aurabase 根据集群的大小将 max_connections 从 50(免费层)到 400(企业层)变化。
#
诊断

为什么 Postgres 连接比应用程序线程花费更多

Postgres 的连接不使用轻量级线程池。每个客户端连接都会触发一个成熟的系统进程。

postmaster 进程为每次连接尝试创建一个新的(“分叉”),专用于该单个会话,直到它关闭。官方项目文档在其架构基础知识章节中准确地描述了这种机制(postgresql.org/docs/current/connect-estab.html,“连接语义”部分,2026 年 8 月 24 日访问)。

这种选择有一个真正的优势:一个连接的崩溃不会影响其他连接,每个进程都与服务器的其余部分隔离。它还具有直接成本:每个额外的连接都会增加一个要调度的整个操作系统进程,以及其自己的内存空间和自己的内核上下文切换开销。

实践中有何变化

在没有池的情况下打开 500 个与 Postgres 的直接连接的应用程序会强制服务器管理 500 个并发系统进程,即使其中绝大多数在两个请求之间保持空闲状态。

#
内存成本

连接实际消耗的内容:共享内存和work_mem

两种不同的机制会影响记忆,混淆它们几乎总是会导致误诊。

第一个是固定的。启动时,Postgres 会根据 max_connections 的值保留共享内存结构(锁、进程表),无论这些连接随后是否打开。该设置的官方文档明确指出:增加它可能需要比操作系统默认配置允许的更多的系统共享内存(postgresql.org/docs/current/runtime-config-connection.html,于 2026 年 8 月 24 日访问)。

第二个是可变的,并且在规模上更加危险:work_mem 不是每个连接分配一次,而是查询计划中的每个排序或散列操作分配一次。官方文档在这一点上很明确:一个复杂的查询可以并行启动其中多个操作,多个会话可以同时执行相同的操作,因此实际使用的内存可能是 work_mem 的几倍(postgresql.org/docs/current/runtime-config-resource.html,访问于 2026 年 8 月 24 日)。

真正要记住的最坏情况

威胁服务器内存的不仅仅是 max_connections × work_mem。它是 max_connections × work_mem × 每个查询的并发操作数。正是这个产品解释了服务器在 max_connections 增加后交换或耗尽内存的情况被认为是无害的。

#
公式

PostgreSQL wiki 大小调整公式

官方 PostgreSQL 项目 wiki 记录了一个基准公式,用于计算您的硬件可以有效并行处理的活动 连接 数量,而不是总共打开的连接数量(wiki.postgresql.org/wiki/Number_Of_Database_Connections,于 2026 年 8 月 24 日访问)。

公式

理想的活跃并发数=(物理核心数×2)+高效磁盘。核心数量不包括超线程。在现代 SSD 存储上,有效磁盘的数量仍然接近 1,其中单独的物理磁盘(“主轴”)的概念失去了其原始含义。

在具有 8 个物理核心和 SSD 存储的服务器上,该公式给出在吞吐量开始下降之前的 (8 × 2) + 1 = 17 个活动连接。这个数字常常令人惊讶:与应用程序在实践中打开的数百个连接相比,它似乎很小。这正是下一段的主题。

The number calculated by the formula measures the concurrency that the CPU and disk can absorb, not the number of client connections your application needs to open. A fleet of 20 application processes, each with its own pool of 10 connections, opens 200 simultaneous connections to Postgres even if only 17 of them are actively working at any given time. Without a pooler, max_connections must cover the 200, not the 17. It is this gap that pushes most architectures to add a pooler in transaction mode, even if it means choosing which one (see our comparison PgBouncer, Supavisor and PgCat).

#
程序

如何更改 max_connections(以及为什么需要重新启动)

max_connections 不支持热插拔。这是一个 postmaster 上下文参数:Postgres 在启动时读取一次,以调整其共享内存的大小。重新加载配置(pg_reload_conf() 或 SIGHUP)是不够的,您必须重新启动服务器。

首先检查当前值及其上下文,以确认是否需要重新启动:

psqlsql
SHOW max_connections;

SELECT name, setting, context
FROM pg_settings
WHERE name = 'max_connections';

-- context='postmaster' 确认需要重新启动

然后应用新值,然后重新启动:

psqlsql
ALTER SYSTEM SET max_connections = '300';

-- 写在postgresql.auto.conf中。
-- 重新启动 Postgres 后才生效。
terminalbash
# 与系统
sudo systemctl restart postgresql

# 不使用systemd,直接使用pg_ctl
pg_ctl restart -D $PGDATA -m fast
许多人忘记的边际

max_connections 默认包括 superuser_reserved_connections (默认为 3):这些连接是为超级用户保留的,以防饱和,它们永远不可用于您的应用程序,即使尚未达到全局计数器也是如此。

#
已签入代码

Aurabase 如何预算其 Postgres 集群上的 max_connections

调整 max_connections 的大小不仅仅是一个理论练习。以下是 Aurabase 如何在其托管 Postgres 集群上进行预算:

100
邮政默认值
任何调整之前的 max_connections
50→400
专用 AURABASE 轴承
CNPG集群对企业免费
3
超级用户保留
superuser_reserved_connections,Postgres 默认值

专用集群:每个项目一个 Postgres 集群

在这个级别上(请参阅我们的比较 专用与共享基础),每个项目都会收到自己的 CloudNativePG 集群和自己的 max_connections 预算,其大小取决于实例的大小:

免费(专用)最大连接数 501 个实例 · 500m vCPU · 512Mi
专业版(默认)最大连接数 2002 个实例 · 1 个 vCPU · 2Gi
团队最大连接数 3003 个实例 · 2 个 vCPU · 3Gi
商业最大连接数 4003 个实例 · 2 个 vCPU · 4Gi

共享集群:一个组织的多个项目,共享预算

在第二条路径上,同一组织的所有项目都通过共享主节点前面的 CNPG 池化器(PgBouncer,transaction模式)进行连接:

免费最大连接数 50最大客户端连接数 100最大用户连接数 20
亲最大连接数 100最大客户端连接数 200最大用户连接数 60
团队最大连接数 200最大客户端连接数 400最大用户连接数 150

组织中的所有项目都通过共享应用程序角色进行连接。 因此, max_user_connections 单独限制了该角色可以在整个集群中打开的服务器连接总数:这是真正的集群全局保护,而不是 max_client_conn,后者仅限制与池化器本身的客户端连接。

但是,该池化器仅提供 SDK 应用程序流量。 PostgREST 就其本身而言,仍然直接连接到主服务(-rw服务):事务模式下的池化会破坏其模式重新加载机制,该机制侦听名为 pgrst的专用 LISTEN 通道。因此,它自己的连接(共享级别上每个副本 2 个,专用级别上每个副本 10 个)直接计入主节点的 max_connections 预算中,在任何池化器之外,正是下面过程的步骤 1 必须包含的那种“被遗忘”连接。

目前正在校准的数字,假设如此

该代码明确地将这些共享池预算记录为在实际条件下通过测量负载下的 pg_stat_activity 进行校准的起始值,而不是作为已发布基准的固定数字。这与我们的 基准测试方法中描述的规则相同:先测量后调整,而不是猜测然后希望。这些集群在 PostgreSQL 16 上运行,我们的 Postgres 16 vs 17 vs 18比较中记录了这一选择。

#
方法

无需池化即可调整 max_connections 大小的 5 步过程

此过程不依赖于任何特定工具:它适用于任何托管或自托管的 Postgres 服务器。

  1. 计算您的实际客户端连接数。 应用程序进程数乘以其内部池的大小,加上管理工具、复制和监控。设置 max_connections 下限的是这个数字,而不是公式。
  2. 使用 PostgreSQL wiki 中的公式计算硬件的理想并发性:(物理内核 × 2)+ 高效磁盘。该数字表明有多少个连接实际上可以并行工作而不降低吞吐量。
  3. 将 max_connections 设置为高于步骤 1 的实际需要,并为 superuser_reserved_connections 以及在应用程序外部打开自己的连接的任何管理工具留出余量。
  4. 使用 ALTER SYSTEM SET 应用更改,然后重新启动服务器。 这是一个 postmaster 参数:简单的重新加载是不够的,如上所述。
  5. 随着时间的推移监控 pg_stat_activity。 如果空闲连接数大大超过活动连接数,这不是 max_connections 问题:这是您需要在服务器前面设置池化器的信号,而不是更高的数字。

第5步的监控请求,直接可用:

psqlsql
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state
ORDER BY count(*) DESC;
#
警告信号

当公式不再足够时:您需要池化器的迹象

当 max_connections 单独不再足够时,无论其值如何,都会系统地返回三个信号。

  1. FATAL: sorry, too many clients already 错误出现在峰值负载期间,而 pg_stat_activity 显示的大多数连接都处于空闲状态。
  2. 该应用程序在无服务器环境中运行,或者使用临时工作线程(边缘函数、短作业)运行,其打开和关闭连接的速度比 Postgres 的每连接进程模型的设计速度要快得多。
  3. 上述公式和过程已经应用,并且客户端连接的实际需求继续超出在不危及work_mem或shared_buffers的情况下可以分配的可用内存。

在这三种情况下,正确的答案几乎总是位于应用程序和 Postgres 之间的池化器,而不是更高的 max_connections。我们的 比较 PgBouncer、Supavisor 和 PgCat 详细介绍了这三个选项,我们的 交易模式指南 解释了池化器就位后最常见的折衷方案。对于连接之外的所有 Postgres 调整,请参阅我们的 生产 Postgres 调整清单。

#
常见问题解答

常见问题解答

PostgreSQL 的默认 max_connections 是多少?+
100,默认为超级用户保留 3 个连接 (superuser_reserved_connections)。此默认值适用于许多通过池化器的应用程序,但一旦一组应用程序进程各自打开自己的一批连接,如果没有池化,很快就会变得不足。
我们可以在不重新启动 PostgreSQL 的情况下更改 max_connections 吗?+
不。 max_connections 是一个 postmaster 上下文参数:Postgres 在启动时读取一次以调整其共享内存的大小。 ALTER SYSTEM SET 将新值写入 postgresql.auto.conf,但只有完全服务器重新启动才会应用它;重新加载或 SIGHUP 是不够的。
空闲的 PostgreSQL 连接会消耗多少内存?+
没有单一的官方数字:它取决于 work_mem、shared_buffers 和每个会话加载的扩展。然而,记录的是,work_mem 是根据查询中的排序或散列操作分配的,而不是每个连接:因此,单个复杂查询可以在单个活动连接上多次使用 work_mem。
我们是否应该总是更喜欢像 PgBouncer 这样的池化器而不是更高的 max_connections ?+
在大多数情况下,是的,只要实际客户端连接数大大超过 PostgreSQL wiki 公式计算出的理想并发数。事务模式池化器在应用程序端的大量逻辑连接之间汇集少量物理连接。请参阅我们对 PgBouncer、Supavisor 和 PgCat 的比较来选择哪一个。
公式(核心数×2)+高效磁盘到底衡量什么?+
它估计理想的活动并发:给定服务器的 CPU 和磁盘在不降低吞吐量的情况下可以并行处理的请求数,而不是 max_connections 中要打开的连接总数。这是通过测量验证的起点,由官方 PostgreSQL 项目 wiki 记录,而不是硬性限制。
我如何知道我的 Postgres 服务器是否接近其连接限制?+
查询pg_stat_activity并比较活动状态和空闲状态的连接数。大量空闲连接接近 max_connections 上限,并且后面没有活动请求,几乎总是表明需要池化而不是需要进一步提高 max_connections。

准备好部署了吗?

五分钟内完成您的后端。

无需信用卡 · 500 MB 免费 · 50,000 MAU