it-swarm.com.de

So ersetzen Sie Tabellendaten in PostgreSQL atomar

Ich möchte den gesamten Inhalt einer Tabelle ersetzen, ohne eingehende SELECT -Anweisungen während des Prozesses zu beeinflussen.

Der Anwendungsfall besteht darin, eine Tabelle zu haben, in der Postfachinformationen gespeichert sind, die regelmäßig extrahiert werden und die in einer PostgreSQL-Tabelle gespeichert werden müssen. Es gibt viele Clients, die eine Anwendung verwenden, die ständig dieselbe Tabelle abfragt.

Normalerweise würde ich so etwas tun (Pseudocode eingehend) ...

BEGIN TRANSACTION
TRUNCATE TABLE
INSERT INTO
COMMIT

Leider kann die Tabelle während dieses Vorgangs nicht gelesen werden. aufgrund der Zeit, die es dauert INSERT INTO fertigstellen. Der Tisch ist gesperrt.

In MySQL hätte ich ihre atomare RENAME TABLE Befehl, um diese Probleme zu vermeiden ...

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;

Wie kann ich das in PostgreSQL erreichen?

Für die Zwecke dieser Frage können Sie davon ausgehen, dass ich keine Fremdschlüssel verwende.

14
Clarkey

Richtig, das TRUNCATE TABLEBefehl Sie führen "... erhält eine ACCESS EXCLUSIVE-Sperre für jede Tabelle, mit der es arbeitet ", also in Beim ersten SQL-Block, den Sie veröffentlicht haben, werden alle anderen Clients, die nach dieser Zeit versuchen, auf die Tabelle zuzugreifen, blockiert, bis Ihr INSERT beendet ist und Sie COMMIT.

Sie können dieselbe Problemumgehung wie in Ihrem MySQL-spezifischen Code verwenden. Postgres unterstützt ungefähr dieselbe Syntax und weist ein ähnliches Sperrverhalten auf. Nämlich:

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 SHARE 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;

Zusätzlicher Bonus: Postgres unterstützt im Gegensatz zu MySQL tatsächlich Transaktions-DDL. Wenn Sie also die oben genannte Transaktion rückgängig machen müssen, können Sie dies sicher tun.

21