Herokuで実行しているアプリがあります。このアプリには、Postgres 9.2.4(Dev)アドオンがインストールされています。オンラインデータベースにアクセスするには、Navicat Postgresを使用します。 Navicatは、Postgresデータベースとの接続をきれいに閉じない場合があります。その結果、しばらくするとPostgresデータベースへの20以上の接続が開かれます。 Postgresのインストールでは、20の同時接続のみが許可されます。したがって、20以上のオープン接続では、Postgressデータベースに到達できません(接続が多すぎます)。
私はこれがNavicatの問題であることを知っており、そのためにこれを解決しようとしています。しかし、それが発生した場合(接続が多すぎる場合)、どうすれば解決できますか(たとえば、すべての接続を閉じます)。
結果なしで、次のすべてを試しました。
heroku restart
)Postgres側に「死んだ」接続があることは明らかだと思います。しかし、どうすればそれらを閉じることができますか?
たぶん_heroku pg:kill
はあなたのためにできますか? https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall
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'
Heroku documentation (強調は私のものです):
致命的:ロールに対して接続が多すぎます
致命的:ロール「[ロール名]」の接続が多すぎるこれは、ユーザーごとに最大20の接続制限があるスターター層(開発および基本)プランで発生します。 このエラーを解決するには、バックグラウンドワーカーを停止するか、dynoの数を減らすか、時間の経過とともに接続リークが発生した場合にアプリケーションを再起動して、データベースへの接続をいくつか閉じます。Railsアプリケーションでの接続の処理に関する議論はこちらにあります。
Heroku スーパーユーザーアクセスを提供しない のため、オプションは上記に限定されます。
サーバーを再起動
heroku restart --app <app_name>
すべての接続を閉じて再起動します。
スーパーユーザー(例: "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();
_