PostgreSQL 12 之后,别再把复制连接算进 max_connections

2026-09-29 17 预计阅读时间: 1 分钟
来源: postgr.es AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

规划 PostgreSQL 连接容量时,一个常见做法是把应用连接、管理连接和复制连接全部塞进 max_connections 的预算里。这个算法对 PostgreSQL 12 及之后的版本并不准确:WAL sender 已有独立的席位,由 max_wal_senders 控制,不再占用 max_connections。

这不是说复制连接不消耗资源,而是说两个参数负责限制不同类型的连接。把它们混在同一个公式里,会让 max_connections 被无谓调大,也可能掩盖真正不足的 max_wal_senders。

两个参数,各管一排座位

在 PostgreSQL 12 及之后,可以把连接容量理解成两组独立配额:

  • max_connections:面向普通客户端会话,例如应用、管理员和连接池建立的数据库连接。
  • max_wal_senders:面向 WAL sender,也就是用于发送 WAL 的复制连接。

因此,下面这种计算方式不适用于 PostgreSQL 12+:

max_connections = 应用连接 + 管理连接 + 复制连接

更合理的拆分是:

max_connections  = 应用连接 + 运维连接 + 普通连接余量
max_wal_senders  = 预期复制发送端 + 维护任务需求 + 复制余量

这里的“独立”只表示连接名额独立。普通后端与 WAL sender 仍运行在同一个数据库实例中,会共同消耗 CPU、内存、网络带宽和文件描述符。不要因为复制连接不计入 max_connections,就把它们当成零成本连接。

先确认版本与当前配置

在调整参数之前,先检查服务器版本。本文的关键结论针对 PostgreSQL 12 及之后的版本。

下面的命令可以直接运行;如果数据库不在本机,请修改连接参数:

psql -X -d postgres <<'SQL'
SELECT current_setting('server_version') AS server_version,
       current_setting('server_version_num') AS server_version_num;

SHOW max_connections;
SHOW max_wal_senders;
SQL

也可以一次查看参数来源、单位以及是否等待重启:

SELECT name,
       setting,
       unit,
       source,
       pending_restart
FROM pg_settings
WHERE name IN ('max_connections', 'max_wal_senders')
ORDER BY name;

如果 server_version_num 小于 120000,不要直接套用 PostgreSQL 12+ 的容量模型,应按对应大版本的行为重新核对配置。

如何估算 max_wal_senders

不要仅按“当前有几个副本”来配置。更实用的方法是列出所有可能建立 WAL sender 连接的消费者,并为维护操作和短暂重叠留出余量。

例如,某个集群平时有三个复制消费者,升级或切换期间可能临时增加两个,再预留一个维护席位,可以这样估算:

稳定运行需求:3
切换或迁移重叠:2
维护余量:1
max_wal_senders:至少 6

这只是容量规划示例,不是适用于所有集群的固定公式。实际清单可能包括物理备库、逻辑复制消费者,以及会使用复制协议的初始化或备份工具。关键是统计“可能同时存在的 WAL sender”,而不是只统计长期运行的副本数量。

余量也不宜无限增加。更高的上限不能解决网络拥塞、落后副本、WAL 堆积或磁盘容量不足等问题;它只决定系统最多允许多少个 WAL sender。

一次可复制的配置与验证流程

下面演示把 max_wal_senders 设置为 12。请先根据自己的并发复制需求替换这个数字。执行 ALTER SYSTEM 需要足够的数据库权限,而重启命令取决于操作系统和部署方式。

# 1. 写入 PostgreSQL 自动配置文件
sudo -u postgres psql -X -d postgres \
  -c "ALTER SYSTEM SET max_wal_senders = '12';"

# 2. 查看当前值以及是否等待重启
sudo -u postgres psql -X -d postgres -c \
  "SELECT name, setting, source, pending_restart
   FROM pg_settings
   WHERE name = 'max_wal_senders';"

# 3. 该参数需要通过重启使新值生效;服务名请按发行版修改
sudo systemctl restart postgresql

# 4. 验证生效值
sudo -u postgres psql -X -d postgres \
  -c "SHOW max_wal_senders;"

容器或 Kubernetes 环境中,不要直接照搬 systemctl。应修改实例使用的配置来源,再通过对应的控制器、Operator 或编排平台滚动重启。生产环境重启前,还应确认高可用切换策略和业务维护窗口。

配置完成后,可以通过 pg_stat_replication 观察当前活跃的复制发送端:

SELECT pid,
       usename,
       application_name,
       client_addr,
       state,
       sync_state
FROM pg_stat_replication
ORDER BY application_name, pid;

这个视图反映的是当前活动情况,不等于峰值需求。容量评估还应结合切换、扩容、备份和故障恢复期间的并发场景。

调整时最容易踩的三个坑

1. 为复制连接额外放大 max_connections

在 PostgreSQL 12+ 中,这会重复计算连接席位。结果通常是普通连接上限偏大,而真正限制复制连接的 max_wal_senders 可能仍然太小。

2. 只提高上限,不检查认证与网络

max_wal_senders 不是复制功能的总开关。复制用户权限、pg_hba.conf、监听地址、防火墙和 TLS 配置仍可能阻止连接。容量参数正确,并不意味着复制链路一定可用。

3. 把独立配额理解成独立资源

WAL sender 不占 max_connections 的名额,但仍会增加进程、网络和 I/O 压力。调整后应继续监控复制延迟、WAL 保留、磁盘空间和系统资源,而不是只看连接是否成功。

上线前检查清单

  • 确认服务器是否为 PostgreSQL 12 或更高版本。
  • 用 max_connections 预算普通客户端连接,不重复计入 WAL sender。
  • 统计所有可能同时运行的复制消费者和维护工具。
  • 为故障切换、迁移和初始化操作预留适度余量。
  • 修改 max_wal_senders 后安排重启并验证实际值。
  • 使用 pg_stat_replication 检查活动发送端,但不要把瞬时数据当作峰值。
  • 同时检查认证、网络、磁盘和 WAL 保留风险。

最重要的修正很简单:从 PostgreSQL 12 开始,普通客户端与 WAL sender 各有自己的连接配额。容量规划时把这两排座位分开计算,配置会更准确,故障排查也会更直接。


相关推荐