解决 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 数据库服务器配置了最多 90 个连接。需要注意的是,数据库会保留一些连接供内部使用。实际可供客户端使用的连接数甚至更少。运维为每个客户端应用配置的连接池大小为 30。
现在,假设运维从 Client-1 开始依次启动 Client 应用。当 Client-4 试图启动时,由于 Client-1、Client-2 和 Client-3 已经创建并阻塞了 90 个连接。因此,当 Client-4 向数据库服务器请求出创建 30 个连接时,服务器拒绝了请求,并显示错误 “FATAL: sorry, too many clients already”。
当开发人员尝试使用 psql、psgAdmin、DBeaver 等数据库管理工具连接 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')
显示连接详细信息的输出示例如下:
各列的含义如下:
列 | 说明 |
---|---|
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 群集之类的环境中自动产生新进程时,数据库中的连接大小可能不足以处理更多的连接请求。
开发人员应在应用中设置适当的 连接超时,并适当关闭连接。这样,连接就不会被长时间保留,并返回到池或数据库服务器。
开发人员在完成工作后,应立即退出 pgAdmin、DBeaver 等数据库管理工具。配置这些工具,使其在一段时间不活动后关闭连接和会话,是一种很好的做法。
运维和网络工程师应限制与数据库服务器的连接。此外,数据库管理员可以对数据库进行配置,以管理允许连接的源 IP。
5、总结
本文介绍了如何解决 PostgreSQL 异常:“FATAL: sorry, too many clients already”,以及该异常出现的原因和避免该异常的最佳实践。
Ref:https://www.baeldung.com/sql/psqlexception-fatal-sorry-too-many-clients-already-solution