如何自动关闭PostgreSQL中的空闲连接?

时间:2012-09-12 15:04:09

标签: postgresql timeout connection

某些客户端连接到我们的postgresql数据库,但保持连接打开。 是否有可能告诉Postgresql在一定量的不活动后关闭这些连接?

TL; DR

  

如果您使用的是Postgresql版本> = 9.2
        然后使用the solution I came up with

     

如果您不想写任何代码
   然后使用arqnid's solution

5 个答案:

答案 0 :(得分:39)

对于那些感兴趣的人,这是我提出的解决方案,灵感来自Craig Ringer的评论:

  

(...)使用cron作业来查看连接最后一次处于活动状态(请参阅pg_stat_activity)并使用pg_terminate_backend来删除旧的。(...)

选择的解决方案如下:

  • 首先,我们升级到Postgresql 9.2。
  • 然后,我们安排一个线程每秒运行一次。
  • 当线程运行时,它会查找任何旧的非活动连接。
      
        
    • 如果状态idleidle in transactionidle in transaction (aborted)disabled,则该连接被视为无效
    •   
    • 如果连接的状态在超过5分钟内保持不变,则该连接被视为
    •   
  • 还有其他线程与上面相同。但是,这些线程使用不同的用户连接到数据库。
  • 我们为连接到我们数据库的任何应用程序保留至少一个连接。 (rank()功能)

这是由线程运行的SQL查询:

WITH inactive_connections AS (
    SELECT
        pid,
        rank() over (partition by client_addr order by backend_start ASC) as rank
    FROM 
        pg_stat_activity
    WHERE
        -- Exclude the thread owned connection (ie no auto-kill)
        pid <> pg_backend_pid( )
    AND
        -- Exclude known applications connections
        application_name !~ '(?:psql)|(?:pgAdmin.+)'
    AND
        -- Include connections to the same database the thread is connected to
        datname = current_database() 
    AND
        -- Include connections using the same thread username connection
        usename = current_user 
    AND
        -- Include inactive connections only
        state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled') 
    AND
        -- Include old connections (found with the state_change field)
        current_timestamp - state_change > interval '5 minutes' 
)
SELECT
    pg_terminate_backend(pid)
FROM
    inactive_connections 
WHERE
    rank > 1 -- Leave one connection for each application connected to the database

答案 1 :(得分:13)

通过像PgBouncer这样的代理连接,这将在server_idle_timeout秒后关闭连接。

答案 2 :(得分:4)

如果您使用的是PostgreSQL> = 9.6,那么还有一个更简单的解决方案。假设您想每5分钟删除一次所有空闲连接,只需运行以下命令:

alter system set idle_in_transaction_session_timeout='5min';

如果您无权以超级用户身份访问(例如Azure云上的示例),请尝试:

SET SESSION idle_in_transaction_session_timeout = '5min';

但是后者仅适用于当前会话,很可能不是您想要的。

禁用该功能,

alter system set idle_in_transaction_session_timeout=0;

SET SESSION idle_in_transaction_session_timeout = 0;

(顺便说一下,默认值为0)。

如果使用alter system,则必须重新加载配置才能开始更改,并且更改是持久的,例如,如果您将重新启动服务器,则不必再运行查询。 / p>

要检查功能状态:

show idle_in_transaction_session_timeout;

答案 3 :(得分:2)

如果将AWS与PostgreSQL> = 9.6一起使用,则必须执行以下操作:

创建自定义参数组

转到RDS>参数组>创建参数组 选择您使用的PSQL版本,将其命名为“ customParameters”或其他名称,并添加描述“处理空闲连接”。

更改idle_in_transaction_session_timeout值

幸运的是,它将创建默认AWS组的副本,因此您只需要调整您认为不适合用例的内容即可。

现在单击新创建的参数组并搜索'idle'。
“ idle_in_transaction_session_timeout”的默认值设置为24小时(86400000毫秒)。将该数字除以24可得到小时数(3600000),然后必须再次将3600000除以4、6或12,具体取决于您是希望将超时分别设为15分钟,10分钟还是5分钟(或等效地乘以分钟数x 60000,因此请在5分钟内输入300,000)。

分配组

最后但并非最不重要的一点是,更改组:

转到RDS,选择您的数据库,然后单击“修改”。

现在在“数据库选项”下,您将找到“数据库参数组”,将其更改为新创建的组。

然后,您可以决定是否要立即应用修改(请注意停机时间)。

答案 4 :(得分:2)

我遇到了连接被拒绝的问题,因为在Postgresql 12服务器上(但在使用较早版本9.6和10的类似项目中)和Ubuntu 18上连接的客户端过多。

我想知道这些设置

tcp_keepalives_idle 
tcp_keepalives_interval 

可能比

更相关
idle_in_transaction_session_timeout

idle_in_transaction_session_timeout 实际上仅关闭失败事务的空闲连接,而不关闭其语句正确终止的非活动连接... 该文档显示,这些套接字级别的设置对Unix域套接字没有影响,但可以在Ubuntu上使用。

相关问题