ロックを待機しているPostgreSQLのALTER TABLEクエリをキャンセルしても安全ですか?


10

ALTER TABLE数時間前にクエリを開始しましたpg_stat_activityが、ロックを待機していることが(を介して)最近認識されました。変更したいテーブルをロックしていて、それを手放さない他のクエリを発見しました。

このクエリは(列のデータ型を変更する)「単純な」クエリですが、大規模なテーブルで実行されています。

ロックを保持しているプロセスを強制終了するのではなく、を強制終了することにしましたALTER TABLE

トランザクションでラップしませんでしたALTER TABLE

私の理解する限り、クエリがロックを待機しているという事実は、常にロックを待機していて、何も変更していないことを意味します。

これは本当ですか?ALTER TABLEクエリを完全にキャンセルしても安全ですか?または、クエリがすでに何かを変更していて、それをキャンセルすると、データベースが何らかの中間状態になる可能性がありますか?

PS:を使用してキャンセルする予定ですSELECT pg_cancel_backend(pid);。これが悪い考えであるなら、私に知らせてください。


1
ALTER TABLEをキャンセルしても問題ありません。PostgreSQLにはトランザクションDDLがあり、ALTER TABLEをまったく実行しなかった場合と同じ状態にしておく必要があります。
Josh Kupershmidt、2015

では、PostgreSQLにトランザクションDDLがあると言うと、スキーマ変更クエリは基本的にトランザクション内で実行されるということですか?
JMTyler 2015

1
あなたの場合、あなたが「ALTER TABLEをトランザクションにラップしなかった」と言ったので、ALTER TABLEは「本質的にトランザクション内で実行されました」。ただし、必要に応じて、BEGINと記述できます。ALTER TABLE foo ...; ALTER TABLEバー...; など; コミット; -これが、トランザクションDDLを持つPostgreSQLの真のキラー機能です。しかし、当面の状況では、はい。ALTERTABLE自体は安全にキャンセルでき、発生しなかったかのようにロールバックされます。
Josh Kupershmidt、2015

迅速な返信ありがとうございました!これはとても良い情報です。承認済みとしてマークできるように、回答として投稿してもらえますか?
JMTyler 2015

回答:


13

私の理解する限り、クエリがロックを待機しているという事実は、常にロックを待機していて、何も変更していないことを意味します。

正しい-pg_stat_activity.waitingがALTER TABLEに対して「true」であることがわかった場合、ほぼ確実に、ターゲットテーブルのACCESS EXCLUSIVEロックとその実際の作業(必要に応じてテーブルを書き換え、カタログを変更する)を辛抱強く待っていることを意味します、インデックスの再構築など)はまだ開始されていません。

ALTER TABLEクエリを完全にキャンセルしても安全ですか?または、クエリがすでに何かを変更していて、それをキャンセルすると、データベースが何らかの中間状態になる可能性がありますか?

PostgreSQLでのクエリのキャンセル(または、トランザクションのロールバック)には、他の特定のデータベースで引き起こされたデータベース破損の危険性はありません(このページの下部にある恐ろしい警告など)。そのため、最近のバージョンでは、非スーパーユーザーが自由に使用しpg_cancel_backend()たりpg_terminate_backend()、他のバックエンドで実行されている自分のクエリを強制終了したりできます。データベースの破損を心配することなく、安全に使用できます。結局のところ、PostgreSQLは、OOMキラーからのSIGKILL、サーバーのシャットダウンなど、プロセスが強制終了する場合に備えて準備する必要があります。それがWALログの目的です。

また、PostgreSQLでは、(マルチステートメント)トランザクション内にネストされたほとんどのDDLコマンドを実行することが可能であることがわかります。

BEGIN;
ALTER TABLE foo ...;
ALTER TABLE bar ...;
-- more stuff
COMMIT; -- or ROLLBACK; if you've changed your mind

(スキーマの移行が完全に行われるか、まったく行われないかを確認するのに最適です。)ただし、次のように述べています。

トランザクションでラップしませんでしたALTER TABLE

単一のコマンドで問題ありません - ドキュメントから、

PostgreSQLは実際にはすべてのSQLステートメントをトランザクション内で実行されているものとして扱います。BEGINコマンドを発行しない場合、個々のステートメントには暗黙のBEGINおよび(成功した場合は)COMMITが含まれます。BEGINとCOMMITで囲まれたステートメントのグループは、トランザクションブロックと呼ばれることもあります。

したがってALTER TABLE、を介して、pg_cancel_backend()または制御しているpsqlプロンプトから発行されたCtrl-C をキャンセルすると、完了した場合と同様の効果があります。

BEGIN;
ALTER TABLE ... ;
ROLLBACK;

(うまくいけばわかるように、とにかくALTER TABLE行く場合は、高価なものをキャンセルすることで、データベースを多くの不要な粉砕から節約できますROLLBACK。)


5

ジョシュの正解と優れた答えを詳しく説明するには:

ALTER TABLEクエリを完全にキャンセルしても安全ですか?

はい。

テーブルの書き換え途中でも安心です。

必要な場合は、PostgreSQLサーバー全体、または実際にはPostgreSQLサーバーが稼働しているマシンをシャットダウンして再起動すれば、すべてが正常に終了します。PostgreSQLのDDLはトランザクション対応であり、クラッシュしても安全です。

DDL操作はWALを介してログに記録され、クラッシュまたは異常終了後の回復時にロールバックまたは完了できることが保証されています。


3
「PostgreSQLサーバー全体をシャットダウンするか、実際にPostgreSQLサーバーを実行し、再起動すれば、すべてが正常に終了する」というメモのみ-fsyncに関係のない信頼性の高いハードウェアがある限り、かなり当てはまります。 、wiki.postgresql.org / wiki / Reliable_Writes
Josh Kupershmidt

2
@JoshKupershmidtもちろん、それはDDLに固有のものではありません。同期の問題がある場合、すべてに対してクラッシュの危険性があります
クレイグリンガー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.