空闲PostgreSQL连接是否有超时?

Is there a timeout for idle PostgreSQL connections?

1
2
1 S postgres  5038   876  0  80   0 - 11962 sk_wai 09:57 ?        00:00:00 postgres: postgres my_app ::1(45035) idle                                                                                
1 S postgres  9796   876  0  80   0 - 11964 sk_wai 11:01 ?        00:00:00 postgres: postgres my_app ::1(43084) idle

我看到很多。我们正在设法修复我们的连接泄漏。但同时,我们想为这些空闲连接设置一个超时,可能最多5分钟。


听起来您的应用程序中存在连接泄漏,因为它无法关闭池连接。您不只是在 in transaction会话上遇到问题,而是在总体上有太多的连接。

消除连接并不是正确的答案,但这是一个不错的临时解决方案。

与其重新启动PostgreSQL从PostgreSQL数据库中启动所有其他连接,不如看:如何从Postgres数据库中分离所有其他用户?如果有活动连接,如何删除PostgreSQL数据库?。后者显示更好的查询。

对于设置超时,正如@doon建议的那样,看看如何自动关闭PostgreSQL中的空闲连接?,建议您使用pgbouncer代理PostgreSQL并管理空闲连接。如果您有一个错误的应用程序无论如何都会泄漏连接,那么这是一个非常好的主意;我强烈建议您配置pgbouncer。

一个tcp-keepalive在这里不能做这个工作,因为这个应用程序仍然是连接的并且是活动的,它不应该是这样的。

在PostgreSQL 9.2及更高版本中,可以使用新的state_changetimestamp列和pg_stat_activitystate字段来实现空闲连接收割机。让cron作业运行如下:

1
2
3
4
5
6
SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'regress'
      AND pid <> pg_backend_pid()
      AND state = 'idle'
      AND state_change < CURRENT_TIMESTAMP - INTERVAL '5' MINUTE;

在旧版本中,您需要实现复杂的方案,以跟踪连接何时空闲。不用麻烦,只要使用PGBOUNCER。


在PostgreSQL 9.6中,有一个新的选项idle_in_transaction_session_timeout,它应该实现您所描述的。您可以使用SET命令进行设置,例如:

1
SET SESSION idle_in_transaction_session_timeout = '5min';


在PostgreSQL 9.1中,具有以下查询的空闲连接。它帮助我避免了重启数据库时出现的情况。这主要发生在JDBC连接打开和未正确关闭的情况下。

1
2
3
4
5
6
7
8
SELECT
   pg_terminate_backend(procpid)
FROM
   pg_stat_activity
WHERE
   current_query = '<IDLE>'
AND
   now() - query_start > '00:10:00';


如果您使用的是PostgreSQL 9.6+,那么可以在postgreSQL.conf中设置

idle_in_transaction_session_timeout = 30000(毫秒)