Chris van Eijk:PostgreSQL 中连接槽位已被保留

Chris van Eijk:PostgreSQL 中连接槽位已被保留

💡 原文英文,约1200词,阅读约需5分钟。
📝

内容提要

PostgreSQL连接槽位耗尽时,max_connections统计所有客户端连接,其中superuser_reserved_connections(默认3)保留给超级用户;PG16起新增reserved_connections,保留给pg_use_reserved_connections角色成员。普通角色用尽普通槽位后报“remaining connection slots are reserved”,全部占满则报“too many clients already”,均为SQLSTATE 53300。释放槽位需查pg_stat_activity;杀客户端不会立即释放,pg_terminate_backend可立即释放;设置idle_in_transaction_session_timeout可清理空闲事务。提高max_connections需重启,多租户SaaS宜用连接池。

🔎

延伸解读

保留槽位的层级与版本差异

文章实测显示,PostgreSQL 的保留槽位并非单一机制。15 版只有 superuser_reserved_connections(默认 3),普通角色用尽非保留槽位后即报错;16 和 17 版新增 reserved_connections,供 pg_use_reserved_connections 角色成员使用,且该保留先于超级用户保留被消耗。这意味着升级到 16 及以上版本后,运维、监控或迁移角色可在普通槽位耗尽时仍连入,但需显式授予角色成员资格并设置 reserved_connections 大于零。

释放槽位的实际延迟与应对

文章强调,杀掉客户端进程并不会立即释放服务端槽位。实测中,客户端被杀后服务端会话仍继续执行查询,直到查询结束尝试返回结果时才察觉客户端已消失。若需立即释放,应使用 pg_terminate_backend(pid) 从服务端终止会话;或设置 client_connection_check_interval 让服务端定期检测客户端断连。对于空闲事务,可设置 idle_in_transaction_session_timeout,但该设置仅对新会话生效,已存在的会话不受影响。

保留槽位的代价与适用场景

保留槽位是从普通角色可用连接数中划出的。文章实测中,max_connections=10、superuser_reserved_connections=3、reserved_connections=2 时,普通应用角色只能建立 5 个连接,而非 7 个。因此,reserved_connections 适合为监控、运维或迁移等关键角色保留紧急入口,但数量应保持较小。对于多租户 SaaS 等连接需求大的场景,文章建议在数据库前使用连接池,让大量客户端连接共享少量服务端会话,而非单纯提高 max_connections。

❓

Q&A

PostgreSQL 报错 'remaining connection slots are reserved' 是什么意思?

该错误表示服务器几乎已满:普通角色可用的连接槽位已全部被占用,剩余槽位保留给超级用户(以及 PostgreSQL 16 起保留给指定角色)。错误码为 SQLSTATE 53300。

为什么普通用户连接 PostgreSQL 时会被拒绝,而超级用户还能连?

因为 max_connections 统计所有客户端连接,其中 superuser_reserved_connections(默认 3)保留给超级用户。普通角色只能使用剩余槽位,用尽后即被拒绝;超级用户仍可使用保留槽位。

PostgreSQL 16 的 reserved_connections 参数有什么作用?

PostgreSQL 16 新增 reserved_connections,用于保留槽位给具有 pg_use_reserved_connections 角色权限的成员。这些槽位可用于监控、运维或迁移等紧急用途,而无需授予超级用户权限。该参数在 PostgreSQL 15 中不存在。

如何释放 PostgreSQL 中被占用的连接槽位?

首先查询 pg_stat_activity 查看谁占用了连接。杀死客户端不会立即释放槽位,需等待查询结束;使用 pg_terminate_backend(pid) 可立即释放。设置 idle_in_transaction_session_timeout 可自动清理空闲事务会话。

提高 max_connections 能解决连接槽位不足的问题吗?

提高 max_connections 只是移动了限制,并未解决根本原因。修改需要重启服务器,且每个连接都是独立的服务器进程。对于多租户 SaaS 应用,更推荐在数据库前使用连接池。

在 PostgreSQL 15 和 16/17 中,连接槽位耗尽时的错误消息有何不同?

在 PostgreSQL 15 中,普通角色在仅剩保留槽位时收到 'remaining connection slots are reserved for non-replication superuser connections';在 16/17 中,消息为 'remaining connection slots are reserved for roles with the SUPERUSER attribute',若设置了 reserved_connections,则可能提示保留给 pg_use_reserved_connections 角色成员。所有槽位占满时均报 'sorry, too many clients already'。

🏷️

标签

➡️

继续阅读