web-dev-qa-db-ja.com

Heroku Postgres:接続が多すぎます。これらの接続を強制終了するにはどうすればよいですか?

Herokuで実行しているアプリがあります。このアプリには、Postgres 9.2.4(Dev)アドオンがインストールされています。オンラインデータベースにアクセスするには、Navicat Postgresを使用します。 Navicatは、Postgresデータベースとの接続をきれいに閉じない場合があります。その結果、しばらくするとPostgresデータベースへの20以上の接続が開かれます。 Postgresのインストールでは、20の同時接続のみが許可されます。したがって、20以上のオープン接続では、Postgressデータベースに到達できません(接続が多すぎます)。

私はこれがNavicatの問題であることを知っており、そのためにこれを解決しようとしています。しかし、それが発生した場合(接続が多すぎる場合)、どうすれば解決できますか(たとえば、すべての接続を閉じます)。

結果なしで、次のすべてを試しました。

  • Navicatを閉じてコンピューターを再起動しました(OS X 10.9)
  • Herokuアプリケーション(heroku restart
  • オンラインデータベースを再起動しようとしましたが、これを行うオプションがないことがわかりました
  • OS XからPostgresサーバーのIPへのすべての接続を手動で閉じた
  • ルーターを再起動しました

Postgres側に「死んだ」接続があることは明らかだと思います。しかし、どうすればそれらを閉じることができますか?

31
Jasper Schulte

たぶん_heroku pg:killはあなたのためにできますか? https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall

32
John Beynon

heroku pg:killallは、開いているすべての接続を強制終了しますが、それはあなたのニーズにとっては鈍器かもしれません。興味深いことに、実際に特定の接続を強制終了できます herokuのデータクリップを使用します。

接続の詳細なリストを取得するには、データクリップ経由でクエリを実行できます。

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を除く、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'
15
mgojohn

Heroku documentation (強調は私のものです):

致命的:ロールに対して接続が多すぎます

致命的:ロール「[ロール名]」の接続が多すぎるこれは、ユーザーごとに最大20の接続制限があるスターター層(開発および基本)プランで発生します。 このエラーを解決するには、バックグラウンドワーカーを停止するか、dynoの数を減らすか、時間の経過とともに接続リークが発生した場合にアプリケーションを再起動して、データベースへの接続をいくつか閉じます。Railsアプリケーションでの接続の処理に関する議論はこちらにあります。

Heroku スーパーユーザーアクセスを提供しない のため、オプションは上記に限定されます。

4
Robert H

サーバーを再起動

heroku restart --app <app_name>

すべての接続を閉じて再起動します。

2
Ebin Joy

スーパーユーザー(例: "postgres")として、次のようなクエリを使用して、現在のセッションを除くすべてのセッションを強制終了できます。

_select pg_cancel_backend(pid)
from pg_stat_activity
where pid <> pg_backend_pid();
_

それらが消えない場合は、より強力な「kill」を使用する必要があるかもしれませんが、最初にpg_cancel_backend()で確実にテストしてください。

_select pg_terminate_backend(pid)
from pg_stat_activity
where pid <> pg_backend_pid();
_
1
bma