私たちは_ALTER TABLE
_クエリを数時間前に開始し、最近(_pg_stat_activity
_を介して)ロックを待機していることを認識しました。変更したいテーブルをロックしていて、それを手放さない別のクエリを発見しました。
このクエリは(列のデータ型を変更する)「単純な」クエリですが、大規模なテーブルで実行されています。
ロックを保持しているプロセスを強制終了するのではなく、_ALTER TABLE
_を強制終了することにしました。
notはトランザクションで_ALTER TABLE
_をラップしました。
私の知る限り、クエリがロックを待機しているという事実は、クエリがalwaysがロックを待機していて、何も変更していないことを意味します。
これは本当ですか? _ALTER TABLE
_クエリを完全にキャンセルしても安全ですか?または、クエリがすでに何かを変更していて、それをキャンセルすると、データベースが何らかの中間状態になる可能性がありますか?
PS:計画はSELECT pg_cancel_backend(pid);
を使用してキャンセルすることです。これが悪い考えであるなら、私に知らせてください。
私の理解する限り、クエリがロックを待機しているという事実は、常にロックを待機していて、何も変更していないことを意味します。
正しい-pg_stat_activity.waitingがALTER TABLEに対して「true」であることがわかった場合、ほぼ確実に、ターゲットテーブルのACCESS EXCLUSIVEロックとその実際の作業(必要に応じてテーブルを書き換え、カタログを変更する)を辛抱強く待っていることを意味します、インデックスの再構築など)はまだ開始されていません。
ALTER TABLEクエリを完全にキャンセルしても安全ですか?または、クエリがすでに何かを変更していて、それをキャンセルすると、データベースが何らかの中間状態になる可能性がありますか?
PostgreSQLでクエリをキャンセルする(またはトランザクションをロールバックする)と、他の特定のデータベース(たとえば 恐ろしい警告 の最下部)によって引き起こされた可能性のあるデータベース破損の危険性がなくなります。ページ)。そのため、最近のバージョンでは、スーパーユーザー以外のユーザーがpg_cancel_backend()
とpg_terminate_backend()
を自由に使用して、他のバックエンドで実行されている独自のクエリを強制終了できます。データベースの破損を心配することなく安全に使用できます。 。結局のところ、PostgreSQLは、プロセスが停止した場合に対処できるように準備する必要があります。 OOMキラーからのSIGKILL、サーバーのシャットダウンなど。これが WAL log の目的です。
また、PostgreSQLでは、(マルチステートメント)トランザクション内にネストされたほとんどのDDLコマンドを実行することが可能であることがわかりました。
_BEGIN;
ALTER TABLE foo ...;
ALTER TABLE bar ...;
-- more stuff
COMMIT; -- or ROLLBACK; if you've changed your mind
_
(スキーマの移行が完全に行われるか、まったく行われないかを確認するのに最適です。)ただし、次のように述べています。
_
ALTER TABLE
_をトランザクションにラップしないにしました。
docs から、1つのコマンドで問題ありません。
PostgreSQLは実際にはすべてのSQLステートメントをトランザクション内で実行されているものとして扱います。 BEGINコマンドを発行しない場合、個々のステートメントには暗黙のBEGINおよび(成功した場合は)COMMITが含まれます。 BEGINとCOMMITで囲まれたステートメントのグループは、トランザクションブロックと呼ばれることもあります。
したがって、pg_cancel_backend()
または制御しているpsqlプロンプトから発行されたCtrl-Cを使用して_ALTER TABLE
_をキャンセルすると、実行した場合と同様の効果が得られます
_BEGIN;
ALTER TABLE ... ;
ROLLBACK;
_
(ご存知のように、高価な_ALTER TABLE
_をキャンセルすると、とにかくROLLBACK
に移動するだけであれば、データベースを不要な大量のデータから節約できます。)
ジョシュの正解と優れた答えを詳しく説明するには:
ALTER TABLEクエリを完全にキャンセルしても安全ですか?
はい。
それは安全でしょうそれがテーブルを書き換えている最中であっても。
PostgreSQLサーバー全体、または実際にはPostgreSQLサーバーが稼働しているマシンをシャットダウンして再起動すれば、すべてが正常に終了します。 PostgreSQLのDDLはトランザクション対応であり、クラッシュしても安全です。
DDL操作はWALを介してログに記録され、クラッシュまたは異常終了後の回復時にロールバックまたは完了できることが保証されています。