PostgreSQLでテーブルデータをアトミックに置き換える方法


14

SELECTプロセス中に着信ステートメントに影響を与えることなく、テーブルの内容全体を置換したい。

ユースケースは、定期的に抽出されるメールボックス情報を保存するテーブルを持ち、PostgreSQLテーブルに保存する必要があることです。同じテーブルを常に照会しているアプリケーションを使用している多くのクライアントがいます。

通常、私は(擬似コード着信)のようなことをします...

BEGIN TRANSACTION
TRUNCATE TABLE
INSERT INTO
COMMIT

ただし、残念ながらこのプロセス中にテーブルを読み取ることはできません。INSERT INTO完了するまでに時間がかかるためです。テーブルはロックされています。

MySQLでは、RENAME TABLEこれらの問題を回避するためにアトミックコマンドを使用していました...

CREATE TABLE table_new LIKE table; 
INSERT INTO table_new;
RENAME TABLE table TO table_old, table_new TO table; *atomic operation*
DROP TABLE table_old;

PostgreSQLでこれをどのように実現できますか?

この質問の目的のために、私は外部キーを使用していないと仮定できます。


行を挿入している間、テーブルを読み取れないと思うのはなぜですか?テーブルの切り捨ては、すべてのセッションですぐに有効になります。ただし、挿入(疑似コードが示唆するように、すべてをラップするトランザクション内で行われた場合)は、コミットするまで他のセッションからは見えません。他のセッションはテーブルから選択でき、コミットするまで空のテーブルが表示されます。
-zgguy

1
@zgguy TRUNCATEコマンドはテーブルのAccessExclusiveロックを取得するため、そのトランザクションがコミットまたはロールバックされるまで、他の誰もテーブルから読み取ることができません。
ジョシュKupershmidt

2
delete代わりに使用truncateすると、遅くなりますが、読者をブロックすることはありません。何行削除する必要がありますか?
a_horse_with_no_name

@a_horse_with_no_name通常は20〜30万行で、多くのvarchar列があります。待機時間DELETEとは、INSERTあまりにも長くなります。
クラキー

回答:


20

右、実行中のTRUNCATE TABLE コマンドは「... 操作対象の各テーブルでACCESS EXCLUSIVEロックを取得」しているため、最初に投稿したSQLブロックでは、その時間以降にテーブルにアクセスしようとする他のクライアントはINSERT終了するまでブロックされますあなたもCOMMIT

MySQL固有のコードと同じ回避策を使用できます。Postgresはほぼ同じ構文をサポートしており、同様のロック動作を行います。機知に:

BEGIN;
-- You probably want to make sure that no one else is
-- INSERT / UPDATE / DELETE'ing from the original table, otherwise
-- those changes may be lost during this switchover process. One way
-- to do that would be via:
-- LOCK TABLE "table" IN ROW EXCLUSIVE mode;
CREATE TABLE "table_new" (LIKE "table");
INSERT INTO "table_new" ...;

-- The ALTER TABLE ... RENAME TO command takes an Access Exclusive lock on "table",
-- but these final few statements should be fast.
ALTER TABLE "table" RENAME TO "table_old";
ALTER TABLE "table_new" RENAME TO "table";
DROP TABLE "table_old";

COMMIT;

追加ボーナス:Postgresは、MySQLとは異なり、トランザクションDDLを実際にサポートしているため、上記のトランザクションをロールバックする必要がある場合は、安全にサポートできます。


あなたの答えに感謝します。LOCK TABLEあなたが提案した方法を使用した場合、の前に再度ロック解除する必要がありCOMMITますか、それとも自動的にロック解除されますか?
クラキー

1
編集:このドキュメントには次の文が見つかりました:「UNLOCK TABLEコマンドはありません。ロックは常にトランザクション終了時に解放されます。」
クラキー

1
ここでは不足していることの一つは、まだに属していることを取り付けた制約のすべてである_old
Intellix
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.