尽管我还没有达到 max_connections(最大连接数)限制,但在连接到我的 Amazon Relational Database Service (Amazon RDS) for PostgreSQL 时,我收到了错误“FATAL: remaining connection slots are reserved for non replicate superuser connections”(致命:剩余的连接槽专为非复制超级用户连接保留)。
简短描述
在 Amazon RDS for PostgreSQL 中,非超级用户的实际最大可用连接数的计算方法如下:
max_connections - superuser_reserved_connections - rds.rds_superuser_reserved_connections。
superuser_reserved_connections(超级用户保留连接数)的默认值为 3,rds.rds_superuser_reserved_connections(rds.rds 超级用户保留连接数)的默认值为 2。
例如,假设将 max_connections 的值设置为 100,则非超级用户的实际可用连接数将计算如下:
100 - 3 - 2 = 95。
Amazon CloudWatch 指标 DatabaseConnections 指示在操作系统级别到数据库实例的客户端网络连接数。该指标是通过测量端口 5432 上的实例实际 TCP 连接数计算得出。数据库会话数可能高于此指标值,因为它不包括以下进程:
- 不再有网络连接但未被数据库清理的后端进程。(例如:连接由于网络问题而终止,但是数据库直到试图将输出返回给客户端时才知道。)
- 数据库引擎作业计划程序创建的后端进程。(例如:pg_cron)
- Amazon RDS 连接。
由于连接到 RDS for PostgreSQL 实例的应用程序突然创建并中断连接,您可能会收到此错误。这可能会导致后端连接在一段时间内仍旧处于打开状态。这种情况可能会造成 pg_stat_activity 视图值和 CloudWatch 的 DatabaseConnections 指标值之间出现差异。
解决方法
排查错误
要排查此错误,请完成以下检查:
- 查看 CloudWatch 的 DatabaseConnections 指标。
- 使用 Performance Insights 查看 numbackends 计数器指标。该值提供有关错误发生时的连接数信息。如果您没有开启 Performance Insights,请以主用户身份登录您的实例。然后,通过运行以下查询来查看后端的数量:
SELECT count(*) FROM pg_stat_activity;
如果您发现一些可以终止的空闲连接,则可以使用 pg_terminate_backend() 函数终止这些后端。您可以通过运行以下查询来查看要终止的所有空闲连接。此查询会显示有关处于下列任何状态超过 15 分钟的后端进程信息:“idle”(空闲)、“idle in transaction”(事务处理中空闲)、“idle in transaction (aborted)”[事务处理中空闲(已中止)]和“disabled”(已禁用)。
SELECT * FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
AND state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND state_change < current_timestamp - INTERVAL '15' MINUTE;
**注意:**请务必根据您的使用场景更新查询。
确定所有必须终止的后端进程后,请运行以下查询以终止这些进程。
**注意:**此示例查询会终止所有处于上述任何一种状态超过 15 分钟的后端进程。
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
AND state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND state_change < current_timestamp - INTERVAL '15' MINUTE
AND usename != 'rdsadmin';
要终止所有空闲的后端进程,请运行以下查询:
SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
AND state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND usename != 'rdsadmin';
**注意:**您无法终止使用 rdsadmin 创建的后端进程。因此,您必须将其排除在终止范围之外。
**重要提示:**如果您不能使用 rds_superuser 权限连接到 RDS for PostgreSQL 实例,请考虑正常关闭应用程序以释放一些连接。
管理数据库连接数
使用连接池
在大多数情况下,您可以使用连接池(如 RDS 代理或任何第三方连接池)来管理在任何给定时间打开的连接数。例如,假设您将 RDS for PostgreSQL 实例的最大连接数值设置为 500,则可以通过将连接池配置为最多 400 个连接来防止与 max_connection 相关的错误。
增加 max_connections 的值
您可以考虑根据使用场景增加 max_connections 的值。但根据数据库实例的工作负载和实例类不同,为 max_connections 设置非常高的值可能会导致内存问题。
**注意:**如果您增加了 max_connections 的值,则必须重新启动实例才能使更改生效。
终止空闲连接
您可以将 idle_in_transaction_session_timeout 参数设置为适合您的使用场景的值。在打开的事务处理中处于空闲状态的时间超过此参数中指定时间的任何会话都将被终止。例如,假设将此参数设置为 10 分钟,则事务处理中空闲时间超过 10 分钟的任何查询都将终止。此参数有助于管理卡滞在此特定状态下的连接。
对于 PostgreSQL 版本 14 及更高版本,您可以使用 idle_session_timeout 参数。设置此参数后,任何空闲时间超过指定时间但未在打开的事务处理中的会话都将被终止。
对于 PostgreSQL 版本 14 及更高版本,您可以使用 client_connection_check_interval 参数。借助此参数,您可以在运行查询时设置可选的客户端连接检查间隔时间。检查是通过轮询插槽来执行的。如果内核报告连接已关闭,则此检查允许提前结束长时间运行的查询。在 PostgreSQL 不知道与后端进程的连接丢失的情况下,此参数会有所帮助。
增加 rds.rds_superuser_reserved_connections 的值
您可以考虑增加 rds.rds_superuser_reserved_connections 参数的值。此参数的默认值为 2。增加此参数的值将允许附加了 rds_superuser 角色的用户建立更多连接。具有此角色的用户可以运行管理任务,例如使用 pg_terminate_backend() 命令终止空闲连接。