如何释放客户端应用程序未正确关闭的 PostgreSQL 连接?
我有一个数据挖掘应用程序,它启动多个进程,所有进程都连接到本地 PostgreSQL 9.1 数据库以检索数据。它运行了几个小时,但随后因错误而死机:
FATAL: remaining connection slots are reserved for non-replication superuser connections
研究表明,这很可能是由于应用程序没有正确关闭连接造成的。但是,即使应用程序被终止,这些连接也永远不会被释放。PostgreSQL 是否会在超时后自动关闭连接?
我也尝试将 Postgres 的 max_connections 从 100 增加到 200,但重新启动时出现错误:
2014-02-23 10:51:15 EST FATAL: could not create shared memory segment: Invalid argument
2014-02-23 10:51:15 EST DETAIL: Failed system call was shmget(key=5432001, size=36954112, 03600).
2014-02-23 10:51:15 EST HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter. You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently 36954112 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.
If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter, in which case raising the request size or reconfiguring SHMMIN is called for.
The PostgreSQL documentation contains more information about shared memory configuration.
我的系统是 Ubuntu 12.04,有 8GB 内存,其他所有 PG 设置都是默认设置,所以我不确定为什么它认为系统没有足够的内存。
然后我尝试使用 pgbouncer 来池化和重用连接。这似乎效果更好一些,但即使这样最终还是用完了连接,并给出了错误:
ERROR: no more connections allowed
我该如何进一步诊断和解决这个问题?
答案1
您可以通过更改最大共享内存设置来增加最大连接数,但是如果问题是您的连接未关闭,那么您真的应该解决这个问题。如果软件不受您的控制并且因不关闭连接而出现错误,您可以使用一些 cron 作业,例如:
select pg_terminate_backend(procpid)
from pg_stat_activity
where usename = 'yourusername'
and current_query = '<IDLE>'
and query_start < current_timestamp - interval '5 minutes'
;
这就是我为消除类似有缺陷的软件造成的泄漏连接所采取的方法。
或者,您可以通过具有类似功能的连接池(例如 pgpool)来运行有缺陷的软件,以杀死空闲连接。
笔记:较新版本的 Postgres 的列名略有不同:
select pg_terminate_backend(pid)
from pg_stat_activity
where usename = 'YOURDATABASEUSERNAME*'
and state = 'idle'
and query_start < current_timestamp - interval '5 minutes'
;
答案2
对于较新版本的 PostgreSQL:
select pg_terminate_backend(pid)
from pg_stat_activity
where usename = 'YOUR_DATABASE_USERNAME*'
and state = 'idle'
and query_start < current_timestamp - interval '5 minutes'
;
以上内容将帮助您终止空闲连接。我遇到了同样的问题,但结果发现这是我的 Flask 和 SQLAlchemy 连接数据库的方式存在问题。
*usename 没有拼写错误
答案3
答案4
postgresql.conf 中的 tcpkeepalive 选项
它将根据 TCP KeepAlive 协议自动终止空闲的 tcp 连接。