web-dev-qa-db-ja.com

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

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

select * from pg_stat_activity

エントリの1つに

<IDLE> in transaction

current_query_text列。

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

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

88
alan

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


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

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

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

(Postgresの古いバージョンはpidではなくprocpidを使用します)。最初(左)の列にpidがあり、最初(上)の行はおそらく終了したいクエリです。以下ではpidが1234であると仮定します。

クエリが自分のものであるか、スーパーユーザーアクセスがある場合は、SQLを介して(シェルアクセスなしで)クエリをキャンセルできます。

select pg_cancel_backend(1234);

これは「ソフト」な方法です...クエリはすぐに消えません。それがうまくいかない場合は、代わりにこれを使用してください:

select pg_terminate_backend(1234);

シェルアクセスとrootまたはpostgresのアクセス許可がある場合は、シェルからも実行できます。

kill -INT 1234

それでも解決しない場合は、次を使用します。

kill 1234

しない:

kill -9 1234

...これにより、postgresサーバー全体が炎上してしまうことがよくありますが、postgresを再起動することもできます。 Postgresは非常に堅牢であるため、データは破損しませんが、いずれにしても「kill -9」を使用しないことをお勧めします:-)


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

124
tobixen

これを試して:

select pg_terminate_backend(pid int)

これについての詳細は こちら をご覧ください。これは、システムごとにプロセスを強制終了するよりも、この問題の「クリーンな」解決策です。

36
evgenek

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

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

それからちょうど:

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

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

heroku pg:locksは何もリストしません。heroku pg:ps

詳細については、チェックアウトしてください。
https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall

19
davidfrancisco

次を使用して、1つのクエリでそれを実現できます。

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