解决 PostgreSQL 的 PSQLException: “FATAL: sorry, too many clients already” 异常

1、概览

当 PostgreSQL 服务器无法接受客户端应用的连接请求时,就会抛出 PostgreSQL PSQLException:FATAL: sorry, too many clients already 这个异常。

本文将带你了解如何解决以及防止这个异常。

2、理解问题

DB 服务器启动时的连接数有限。有时,连接会用完。因此,数据库服务器无法提供新的连接。这时,它就会抛出异常:FATAL: sorry, too many clients already

首先,来了解一下这个问题是如何、何时以及为何出现的。假设有四个 Client 应用连接到 PostgreSQL 数据库:

PostgreSQL 与客户端的连接

大多数情况下,应用会在启动时创建数据库连接池。假设数据库管理员为 PostgreSQL 数据库服务器配置了最多 90 个连接。需要注意的是,数据库会保留一些连接供内部使用。实际可供客户端使用的连接数甚至更少。运维为每个客户端应用配置的连接池大小为 30

现在,假设运维从 Client-1 开始依次启动 Client 应用。当 Client-4 试图启动时,由于 Client-1Client-2Client-3 已经创建并阻塞了 90 个连接。因此,当 Client-4 向数据库服务器请求出创建 30 个连接时,服务器拒绝了请求,并显示错误 “FATAL: sorry, too many clients already”。

当开发人员尝试使用 psqlpsgAdminDBeaver 等数据库管理工具连接 PostgreSQL 服务器时,也会出现该错误。因为这些工具也会尝试获取与数据库的连接,如果连接不足,它们也可能遇到同样的错误。

3、排除故障

首先,通过在 PostgreSQL 数据库中运行查询来确定最大连接数:

show max_connections

默认情况下,该值为 100,可以通过修改数据库配置文件 postgresql.conf 中的 max_connections 属性来 设置 它:

/var/lib/postgresql/data # cat postgresql.conf | grep max_connections
max_connections = 100                   # (change requires restart)

不过,应该首先找出数据库连接使用率高的原因,而不是将其设置为更高的值,这样才能找到永久性的解决方案。

当客户端程序抛出此类错误时,我们必须确定数据库服务器的活动连接数。每个活动连接都有一个后端进程在数据库服务器中运行。PostgreSQL 数据库会在 pg_stat_activity 视图中跟踪这些后端进程。

我们可以运行如下 SQL 查询,获取活动连接和空闲连接:

select pid, datname, application_name, client_addr, state 
from pg_stat_activity 
where state in ('idle', 'active')

显示连接详细信息的输出示例如下:

显示 PostgreSQL 连接的详细信息

各列的含义如下:

说明
pid 后台进程的进程 ID
datname 连接的数据库名称
application_name 连接到该进程的应用名称
client_addr 连接到该进程的客户端的 IP 地址
state 该进程当前的状态。可能的值有:active: 正在执行查询。idle:正在等待新的客户端命令

在发现活动连接和空闲连接后,我们可以找出无关紧要的连接,并停止或杀死占用这些连接的后端进程。此外,还可以使用 pg_terminate_backend 系统管理函数从数据库中强制终止会话:

select pg_terminate_backend(147)

数据库函数 pg_terminate_backend() 获取后端进程 ID 147 并终止它。

4、如何防止

防止出现该错误的首要步骤是对应用进行准确的基准测试,以评估其数据库服务器连接需求。基准测试完成后,就可以根据最大连接需求确定数据库服务器的大小和配置。然后,运维团队就可以在应用中设置最佳连接池大小。

此外,在启用自动伸缩的环境中,应该谨慎设置应用进程的连接池大小。当在诸如 Kubernetes 群集之类的环境中自动产生新进程时,数据库中的连接大小可能不足以处理更多的连接请求。

开发人员应在应用中设置适当的 连接超时,并适当关闭连接。这样,连接就不会被长时间保留,并返回到池或数据库服务器。

开发人员在完成工作后,应立即退出 pgAdminDBeaver 等数据库管理工具。配置这些工具,使其在一段时间不活动后关闭连接和会话,是一种很好的做法。

运维和网络工程师应限制与数据库服务器的连接。此外,数据库管理员可以对数据库进行配置,以管理允许连接的源 IP。

5、总结

本文介绍了如何解决 PostgreSQL 异常:“FATAL: sorry, too many clients already”,以及该异常出现的原因和避免该异常的最佳实践。


Ref:https://www.baeldung.com/sql/psqlexception-fatal-sorry-too-many-clients-already-solution