PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Aktualisieren von Datenbankzeilen ohne Sperren der Tabelle in PostgreSQL 9.2

MVCC

Zunächst einmal, wenn "normale Operationen" aus SELECT bestehen Abfragen, das MVCC-Modell kümmert sich automatisch darum. UPDATE blockiert SELECT nicht und umgekehrt. SELECT sieht nur festgeschriebene Daten (oder was in derselben Transaktion gemacht wurde), also das Ergebnis des großen UPDATE bleibt für andere Transaktionen unsichtbar, bis es fertig ist (festgeschrieben).

Leistung / Aufblasen

Wenn Sie haben keine anderen Objekte, die auf diese Tabelle verweisen,
und Sie haben keine gleichzeitigen Schreibvorgänge (die verloren gehen würden!),
und Sie können sich eine sehr kurze exklusive Sperre für den Tisch leisten,
und Sie haben natürlich den zusätzlichen Speicherplatz:
Sie könnten die Sperrung auf ein Minimum reduzieren, indem Sie im Hintergrund eine aktualisierte Version der Tabelle erstellen. Stellen Sie sicher, dass es alles hat um ein Drop-in-Ersatz zu sein, dann lösche das Original und benenne das Dupe um.

CREATE TABLE tbl_new (LIKE tbl_org INCLUDING CONSTRAINTS);

INSERT INTO tbl_new 
SELECT col_a, col_b, array[col] aS col_c
FROM   tbl_org;

Ich verwende CREATE TABLE (LIKE .. INCLUDING CONSTRAINTS) , weil (hier das Handbuch zitieren):

Nicht-Null-Einschränkungen werden immer in die neue Tabelle kopiert. CHECK Einschränkungen werden nur kopiert, wenn INCLUDING CONSTRAINTS angegeben ist; andere Arten von Beschränkungen werden niemals kopiert.

Stellen Sie sicher, dass der neue Tisch fertig ist. Dann:

DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;

Führt zu einem sehr kurzen Zeitfenster, in dem der Tisch exklusiv gesperrt wird.

Hier geht es wirklich nur um Leistung. Es erstellt ziemlich schnell eine neue Tabelle ohne Aufblasen. Wenn Sie Fremdschlüssel oder -ansichten haben, können Sie immer noch diesen Weg gehen, aber Sie müssen ein Skript vorbereiten, um diese Objekte zu löschen und neu zu erstellen, wodurch möglicherweise zusätzliche exklusive Sperren erstellt werden.

Gleichzeitige Schreibvorgänge

Bei gleichzeitigen Schreibvorgängen ist eigentlich alles, was Sie tun können, Ihr Update in Stücke aufzuteilen. Das ist nicht in einer einzigen Transaktion möglich, da Sperren erst am Ende einer Transaktion aufgehoben werden.

Sie könnten Verwenden Sie dblink , die unabhängige Transaktionen auf einer anderen Datenbank, einschließlich sich selbst, starten kann. Auf diese Weise könnten Sie alles in einem einzigen DO erledigen -Anweisung oder eine plpgsql-Funktion mit einer Schleife. Hier ist eine lose verwandte Antwort mit weiteren Informationen zu dblink:

  • Datenbank aus gespeicherter Prozedur in PostgreSQL löschen oder erstellen

Ihr Ansatz mit Cursorn

Ein Cursor innerhalb der Funktion wird Ihnen nichts kaufen . Jede Funktion wird automatisch in eine Transaktion eingeschlossen, und alle Sperren werden erst am Ende der Transaktion aufgehoben. Auch wenn Sie CLOSE cursor verwendet haben (was Sie nicht tun) würde es nur einige Ressourcen freigeben, aber nicht Geben Sie erworbene Sperren für die Tabelle frei. Ich zitiere das Handbuch:

CLOSE schließt das Portal unter einem geöffneten Cursor. Dies kann verwendet werden, um Ressourcen vor dem Ende der Transaktion freizugeben oder um die Cursorvariable freizugeben, damit sie erneut geöffnet werden kann.

Sie müssten separat ausgeführt werden Transaktionen oder (missbrauchen) Sie dblink, das das für Sie erledigt.