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分钟。
- 你是如何连接数据库的?SocketTimeout可能是你想要的。
- 我们有这个传统的幽门网络应用,我们使用了sqlacalchemy,但显然我们没有正确使用它。我不记得了。我们正在设法修补漏洞。文件中的socketTimeout看起来像是完全关闭了与数据库的连接。我正在尝试关闭每个空闲,一旦建立连接,计数器就会启动。
- 请参阅stackoverflow.com/questions/12391174/…
- @用户1012451当您说"关闭每个空闲"时,您的意思是终止 in transaction会话,使会话保持运行但处于状态吗?换句话说,终止事务而不是会话?(投反对票:问题不明)
- @Craigringer一段时间后,我们达到了最大客户机连接。为了解决这个问题,我们必须重新启动webapp,这也强制重新启动postgresql。这会抹掉所有连接。当我们永远看到这些idle时,我们会问是否可以在每个连接/会话上设置超时(我真的不知道正确的术语,抱歉)。如果一个正常的Web应用程序的事务需要5分钟,那么肯定有什么问题……
- 自动重新连接怎么样?
听起来您的应用程序中存在连接泄漏,因为它无法关闭池连接。您不只是在 in transaction会话上遇到问题,而是在总体上有太多的连接。
消除连接并不是正确的答案,但这是一个不错的临时解决方案。
与其重新启动PostgreSQL从PostgreSQL数据库中启动所有其他连接,不如看:如何从Postgres数据库中分离所有其他用户?如果有活动连接,如何删除PostgreSQL数据库?。后者显示更好的查询。
对于设置超时,正如@doon建议的那样,看看如何自动关闭PostgreSQL中的空闲连接?,建议您使用pgbouncer代理PostgreSQL并管理空闲连接。如果您有一个错误的应用程序无论如何都会泄漏连接,那么这是一个非常好的主意;我强烈建议您配置pgbouncer。
一个tcp-keepalive在这里不能做这个工作,因为这个应用程序仍然是连接的并且是活动的,它不应该是这样的。
在PostgreSQL 9.2及更高版本中,可以使用新的state_changetimestamp列和pg_stat_activity的state字段来实现空闲连接收割机。让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。
- 很好,但它会杀死其他PGADMIN后端。使用附加条件应用程序
- 如果我使用pgbouncer,我可以运行pg_terminate_backend吗?
- @我不明白为什么,尽管我没有具体检查。
- 运行这个似乎已经杀死了我的wal sender进程
- @Craigringer甚至PSQL连接都被视为空闲连接。为什么一开始就必须关闭空闲连接?我有一个长时间运行的代码,它与pg建立连接,执行一些dml操作,然后等待队列中的消息,然后再执行一些dml操作。在这段时间内,即在如上所述的等待队列(消息)时,即使与posts的连接是idle。我为什么要关闭它?
- 考虑在"状态"匹配项中添加:state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')。
- 一个问题,PGBOUNCER在这里有什么帮助?当GCP确实杀死了我们可抢占的机器时,我们看到了连接泄漏,不知何故Postgres没有清理连接。PGBOUNCER如何清除这些陈旧的连接?
在PostgreSQL 9.6中,有一个新的选项idle_in_transaction_session_timeout,它应该实现您所描述的。您可以使用SET命令进行设置,例如:
1
| SET SESSION idle_in_transaction_session_timeout = '5min'; |
- 很难问这么简单的问题,但我对数据库是全新的——你能给我一个如何使用这个功能的非常基本的例子吗?
- 没问题,更新了答案。
- 在以前的PostgreSQL版本中有类似的内容吗??
- 不,以前的版本需要类似于其他答案的内容。
- 每次重新启动数据库时是否需要设置此参数?或者在你做了一次之后你可以忘记?谢谢
- SET SESSION仅用于当前会话(一旦打开新连接,它将返回默认值)。您还可以使用ALTER DATABASE SET idle_in_transaction_session_timeout = '5min'或使用配置文件(请参见postgresql.org/docs/current/static/config setting.html)在数据库级别设置配置参数。
在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'; |
- 从8.4开始,pg摼terminate摼backend就在
如果您使用的是PostgreSQL 9.6+,那么可以在postgreSQL.conf中设置
idle_in_transaction_session_timeout = 30000(毫秒)