48

我有一个在 Heroku 上运行的应用程序。这个应用程序安装了 Postgres 9.2.4 (Dev) 插件。要访问我的在线数据库,我使用 Navicat Postgres。有时 Navicat 不会干净地关闭它与 Postgres 数据库建立的连接。结果是一段时间后有 20 多个开放连接到 Postgres 数据库。我的 Postgres 安装只允许 20 个同时连接。因此,由于有 20 多个打开的连接,我的 Postgress 数据库现在无法访问(连接太多)。

我知道这是 Navicat 的问题,我正试图解决这个问题。但是如果它发生(连接太多),我该如何解决这个问题(例如关闭所有连接)。

我已经尝试了以下所有事情,但没有结果。

  • 关闭 Navicat 并重新启动我的电脑 (OS X 10.9)
  • 重新启动我的 Heroku 应用程序 ( heroku restart)
  • 试图重新启动在线数据库,但我发现没有选项可以这样做
  • 手动关闭从 OS X 到 Postgres 服务器 IP 的所有连接
  • 重启我们的路由器

我认为很明显在 Postgres 方面存在一些“死”的联系。但是我该如何关闭它们呢?

4

6 回答 6

41

也许看看heroku pg:kill可以为您做什么?https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall

于 2013-11-06T15:32:40.730 回答
21

heroku pg:killall将杀死所有打开的连接,但这可能是您需要的钝器。有趣的是,您实际上可以使用 heroku 的数据剪辑来终止特定连接。

要获取详细的连接列表,可以通过 dataclips 查询:

SELECT * FROM pg_stat_activity;

在某些情况下,您可能想要终止与 IP 地址相关的所有连接(您的笔记本电脑,或者在我的情况下,是现在被破坏的服务器)。

您可以使用以下命令查看属于每个客户端 IP 的连接数:

SELECT client_addr, count(*) 
FROM pg_stat_activity 
WHERE client_addr is not null 
  AND client_addr <> (select client_addr from pg_stat_activity where pid=pg_backend_Tid()) 
GROUP BY client_addr; 

这将列出每个 IP 的连接数,不包括 dataclips 本身使用的 IP。

要真正终止连接,请将它们的“pid”传递给 pg_terminate_backend()。在简单的情况下:

SELECT pg_terminate_backend(1234)

其中 1234 是您在 pg_stat_activity 中找到的有问题的 PID。

就我而言,我想终止与(现已死亡的)服务器相关的所有连接,所以我使用了:

SELECT pg_terminate_backend(pid), host(client_addr) 
FROM pg_stat_activity 
WHERE host(client_addr) = 'IP HERE'
于 2014-02-05T07:18:41.077 回答
8

Heroku 文档(重点是我的):

致命:角色连接过多

致命:角色“[角色名称]”的连接过多 这发生在 Starter Tier(开发和基本)计划中,每个用户的最大连接限制为 20。要解决此错误,请通过停止后台工作程序、减少 dyno 的数量或重新启动您的应用程序来关闭与数据库的一些连接,以防它随着时间的推移造成连接泄漏。可以在此处找到有关在 Rails 应用程序中处理连接的讨论。

因为 Heroku不提供超级用户访问权限,所以您的选项仅限于上述内容。

于 2013-11-06T14:46:00.283 回答
6

重启服务器

heroku restart --app <app_name>

它将关闭所有连接并重新启动。

于 2018-03-22T10:13:16.793 回答
6

1)。首先使用正确的 id 登录 Heroku(如果您有多个帐户),使用heroku login.
2)。然后,运行heroku apps以获取您的应用程序列表并复制已安装 PostgreSQL 数据库的应用程序的名称。
3)。最后,运行heroku pg:killall --app appname以终止所有连接。

于 2019-09-13T10:40:24.393 回答
2

作为超级用户(例如“postgres”),您可以使用如下查询杀死每个会话,但当前会话除外:

select pg_cancel_backend(pid)
from pg_stat_activity
where pid <> pg_backend_pid();

如果他们不走,你可能不得不使用更强的“杀戮”,但一定pg_cancel_backend()要先测试。

select pg_terminate_backend(pid)
from pg_stat_activity
where pid <> pg_backend_pid();
于 2013-11-06T14:34:17.820 回答