私の理解する限り、クエリがロックを待機しているという事実は、常にロックを待機していて、何も変更していないことを意味します。
正しい-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
。)