规划 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 各有自己的连接配额。容量规划时把这两排座位分开计算,配置会更准确,故障排查也会更直接。