Heroku Postgres-ハングしたクエリの終了(トランザクションのアイドル)


99

私はHerokuをCrane Postgresオプションで使用していて、ローカルマシンがクラッシュしたときにローカルマシンからデータベースでクエリを実行していました。走れば

select * from pg_stat_activity

エントリの1つが

<IDLE> in transaction

current_query_text列。

その結果、終了したクエリによって書き込まれていたテーブルを削除できません。pg_cancel_backend(N)を使用してみましたが、Trueを返しますが、何も起こらないようです。

テーブルを削除できるように、このプロセスを終了するにはどうすればよいですか?


1
たぶん、質問は「postgresサーバーへのrootアクセスも、データベースへのスーパーユーザーアクセスもないときに、自分のクエリを終了するにはどうすればよいですか」と言い換える必要があります。それは確かに非常に良い質問のようです...そして私は答えを知りません。
tobixen

回答:


138

これは一般的なPostgresの回答であり、herokuに固有ではありません


(この質問に対する単純で愚かな答えは... postgresqlを再起動するだけかもしれません。それが望ましくないか、オプションではないと仮定すると...)

次のSQLを実行してPIDを見つけます。

SELECT pid , query, * from pg_stat_activity
  WHERE state != 'idle' ORDER BY xact_start;

(クエリはpostgresのバージョンに応じて修正が必要になる場合があります-最終的には、pg_stat_activityから*を選択するだけです)。pidは最初(左)の列にあり、最初(上)の行は、終了するクエリである可能性があります。pidが1234であると仮定します。

それがあなたのものであるか、あなたがスーパーユーザーアクセス権を持っている限り、あなたはSQLを通して(すなわちシェルアクセスなしで)クエリをキャンセルすることができます:

select pg_cancel_backend(1234);

これは1234クエリをキャンセルする「友好的な」リクエストであり、運が良ければしばらくすると消えます。最終的に、これはより効率的です。

select pg_terminate_backend(1234);

シェルアクセスとrootまたはpostgres権限がある場合は、シェルからも実行できます。「キャンセル」するには、次のようにします。

kill -INT 1234

「終了」するには、次のようにします。

kill 1234

しない:

kill -9 1234

...その結果、postgresサーバー全体が炎上してしまうことがよくあります。その後、postgresを再起動することもできます。Postgresはかなり堅牢なので、データは破損しませんが、どのような場合でも「kill -9」を使用しないことをお勧めします:-)


多くの場合、「アイドル状態のトランザクション」は、トランザクションが「コミット」または「ロールバック」で終了しなかったことを意味します。つまり、アプリケーションにバグがあるか、トランザクションデータベースで動作するように適切に設計されていません。長時間持続する「トランザクションのアイドル」は、パフォーマンス上の大きな問題を引き起こす可能性があるため、避ける必要があります。


pg_cancel_backendを試しましたが、役に立ちませんでした。私は、シェルアクセスを持っていないと私はpg_terminate_backendを使用してSIGKILLを送信することはできませんので、私はスーパーユーザではないよ
アラン・

どのバージョンのpostgresを使用していますか?(ヒント:)select version()。使用時にエラーメッセージが表示されますpg_cancel_backendか?
tobixen

自分でpg_cancel_backendを使用しようとしたため、「他のサーバープロセスに信号を送るにはスーパーユーザーである必要があります」というエラーメッセージが表示されました...つまり、サーバーのrootアクセスまたは一部のpostgresスーパーユーザー(つまり、postgresユーザー)を介したdbアクセスが必要です。 )独自のクエリを強制終了します。それは少し吸うようです:-(
tobixen

1
プロセスはpg_cancel_backendによってキャンセルされていましたが、クエリはしばらくの間pg_stat_activityに表示されます
アラン

おそらくそれはHerokuに固有のものです。私の知る限り、通常のpostgresでは、スタックしたプロセスを強制終了するにはスーパーユーザーである必要があります(私はpg 8.4で「select pg_sleep(3600);」を使用してテストしています)。他のサーバープロセス」)。ただし、ここでも「トランザクションのアイドル」はまったく同じではありません。
tobixen 2012年


19

heroku-pg-extrasアドオンをインストールし、次のコマンドを実行してPIDを取得できます。

heroku pg:locks --app <your-app>

次に、ちょうど行います:

heroku pg:kill <pid> --app <your-app> 

--forceオプションを使用して、そのクエリの接続全体をドロップするpg_terminate_backendを発行できます。

heroku pg:locks何も表示されない場合は、を試してくださいheroku pg:ps

詳細については、https
//devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killallをご覧ください。


ありがとうございました。それでもトランザクション/ PIDを終了できません...インポート中にコンピューターがハードウェアをフリーズし、PIDを終了できません。:(
dimitarvp 2016年

-3

以下を使用して、単一のクエリでそれを実現できます。

SELECT pg_cancel_backend(pid), pg_terminate_backend(pid) FROM pg_stat_activity WHERE state != 'idle';

実行中のすべてのクエリが強制終了されるため、postgresを再起動することもできます。xact_startとlimit 1で注文し、同意することもできます...しかし、もう一度、盲目的に殺す前にリストを確認することをお勧めします。
tobixen

これはどうですか?SELECT pid, pg_cancel_backend(pid) FROM pg_stat_activity WHERE state != 'idle' AND (now() - query_start) > interval '5 minutes';
AFN
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.