09 September 2013

PostgreSQL® 9.3

Fremdschlüssel sind unabdingbar für die referentielle Integrität der Daten. Allerdings brachten diese bis einschließlich PostgreSQL® 9.2 auch unter bestimmten Bedingungen Lockingprobleme bei UPDATE auf Spalten mit Fremdschlüsseln mit sich. Vor allem bei überlappenden Aktualisierungen mehrerer Transaktionen über einen Fremdschlüssel kann es sogar zu Deadlocks kommen. Das folgende Beispiel ist in PostgreSQL® 9.2 problematisch, exemplarisch an diesem einfachen Datenmodell demonstriert:

CREATE TABLE parent(id integer, value text);
ALTER TABLE parent ADD PRIMARY KEY(id);
CREATE TABLE child(id integer, parent_id integer REFERENCES parent(id), value text);
INSERT INTO parent VALUES(1, 'bob');
INSERT INTO parent VALUES(2, 'andrea');

 

Zwei Transaktionen, jeweils Session 1 und Session 2 genannt, werden zeitgleich in der Datenbank gestartet:

Session 1

BEGIN;
INSERT INTO child VALUES(1, 1, 'abcdef');
UPDATE parent SET value = 'thomas' WHERE id = 1;

 

Session 2

BEGIN;
INSERT INTO child VALUES(2, 1, 'ghijkl');
UPDATE parent SET value = 'thomas' WHERE id = 1;

 

Session 1 und Session 2 führen beide den INSERT erfolgreich aus, der UPDATE blockiert jedoch in Session 1, da der INSERT in Session 2 einen sogenannten SHARE LOCK auf das Tupel mit dem Fremdschlüssel hält. Dieser steht in Konflikt mit der Sperre, die der UPDATE auf den Fremdschlüssel haben möchte. Nun versucht Session 2 seinerseits seinen UPDATE abzusetzen, dies erzeugt jedoch wiederum einen Konflikt mit dem UPDATE aus Session 1; Ein Deadlock ist entstanden und wird automatisch in PostgreSQL® 9.2 aufgelöst. In diesem Fall wird jedoch die Transaktion in Session 2 abgebrochen:

ERROR:  deadlock detected
DETAIL:  Process 88059 waits for ExclusiveLock on tuple (0,1) of relation 1144033 of database 1029038; blocked by process 88031.
Process 88031 waits for ShareLock on transaction 791327; blocked by process 88059.

 

In PostgreSQL® 9.3 gibt es jetzt ein deutlich verfeinertes Locking bei Aktualisierungen auf Zeilen und Tabellen mit Fremdschlüsseln, die das angeführte Problem entschärfen. Hierbei werden Tupel, die kein gezieltes UPDATE auf einen Fremdschlüssel darstellen (d.h. der Wert eines Fremdschlüssels wird nicht verändert), mit einem schwächeren Lock (FOR NO KEY UPDATE) gesperrt. Für das einfache Prüfen eines Fremdschlüssels verwendet PostgreSQL® des weiteren den neuen FOR KEY SHARE Lock, der hiermit nicht in Konflikt steht. Dies verhindert im gezeigten Beispiel einen Deadlock, der UPDATE in Session 1 wird zunächst ausgeführt, der in Konflikt stehende UPDATE in Session 2 muss warten, bis Session 1 erfolgreich die Transaktion bestätigt oder zurückrollt.

Parallel pg_dump

pg_dump besitzt mit der neuen Kommandozeilenoption -j die Möglichkeit, parallel Tabellen und deren Daten zu sichern. Diese Funktion kann einen Dump sehr großer Datenbanken erheblich beschleunigen, da Tabellen gleichzeitig gesichert werden können. Dies funktioniert nur mit dem Directory Ausgabeformat (-Fd) von pg_dump. Mittels pg_restore können diese Dumps dann ebenfalls mit mehreren Restoreprozessen gleichzeitig wiederhergestellt werden.

Updatable Foreign Data Wrapper und postgres_fdw

Mit PostgreSQL® 9.3 wurde die API für Foreign Data Wrapper (FDW) für DML-Kommandos erweitert. Dies ermöglicht die Implementierung von aktualisierbaren FDW-Modulen. Gleichzeitig wurde der Foreign Data Wrapper für PostgreSQL® (postgres_fdw) als Extension integriert. Dies erlaubt nun den transparenten Zugriff auf entfernte PostgreSQL®-Instanzen. Tabellen erscheinen dabei in der Datenbank als lokale Tabellen und können ohne weiteres zum Beispiel in komplexen SQL-Konstrukten wie JOINs oder Views verwendet werden. FDW werden in einem späteren Artikel an dieser Stelle noch ausführlicher erläutert.

Event Trigger

Ein schon länger von Anwendern gewünschtes Feature sind Event Trigger für DDL (Data Definition Language) Operationen, wie beispielsweise ALTER TABLE oder CREATE TABLE. Dies ermöglicht das automatische Reagieren auf bestimmte Ereignisse per DDL, wie beispielsweise bestimmte Aktionen zu protokollieren. Unterstützt werden im Moment Aktionen für ddl_command_start, sql_drop und ddl_command_end. Triggerfunktionen können mit C oder PL/PgSQL erstellt werden. Folgendes Beispiel für sql_drop verhindert beispielsweise das Löschen von Tabellen:

CREATE OR REPLACE FUNCTION del_event_func() RETURNS event_trigger AS $$
DECLARE
        v_item record;
BEGIN
        FOR v_item IN SELECT * FROM pg_event_trigger_dropped_objects()
        LOOP
                RAISE EXCEPTION 'deletion of object %.% forbidden', v_item.schema_name, v_item.object_name;
        END LOOP;
END;
$$ LANGUAGE plpgsql;
 
CREATE EVENT TRIGGER delete_table_obj ON sql_drop WHEN tag IN ('drop table') EXECUTE PROCEDURE del_event_func();
 
DROP TABLE child ;
FEHLER:  deletion of object public.child forbidden

Prüfsummen in Tabellen

Mit PostgreSQL® 9.3 gibt es nun die Möglichkeit, in Umgebungen, in denen die Zuverlässigkeit der verwendeten Speicherlösungen nicht garantiert werden kann (beispielsweise bestimmte Cloudumgebungen), den Datenbankcluster mit Prüfsummen zu initialisieren. PostgreSQL® organisiert Tupel in standardmäßig 8KB großen Blöcken. Diese bilden die kleinste Einheit, mit der die Datenbank auf dem Speichersystem arbeitet. Prüfsummen versehen diese Blöcke nun mit zusätzlichen Informationen, um Speicherfehler wie korrupte Blockheader oder Tupelheader frühzeitig erkennen zu können. Prüfsummen lassen sich nicht nachträglich aktivieren, sondern erfordern das Initialisieren des physikalischen Datenbankverzeichnisses mit initdb und dem neuen Kommandozeilenparameter –data-checksums. Dies gilt dann für sämtliche Datenbankobjekte wie Tabellen oder Indexe und hat eine Auswirkung auf die Geschwindigkeit.

Materialized Views

Die neue PostgreSQL® Version 9.3 enthält nun auch eine grundlegende Implementierung für Materialized Views. Normale Views in PostgreSQL® sind keine materialisierten Objekte im Sinne einer Tabelle. Im übertragenen Sinne muss man sich Views als eine Art Makro vorstellen, die PostgreSQL®auf die zugrundeliegende View anwendet. So wird ein SELECT * FROM <view> dann zum eigentlichen, beliebig komplexen SELECT umgeschrieben. Dies hat jedoch zur Folge, dass bei großen Datenmengen immer wieder das Ergebnis von neuem geplant, ausgeführt und materialisiert werden muss. Mit Materialized Views lassen sich Views erstellen, die die materialisierte Ergebnismenge direkt vorhalten. Die Implementierung in PostgreSQL® 9.3 ist jedoch noch sehr generisch. Auch blockiert das  REFRESH MATERIALIZED VIEW Kommando alle Zugriffe auf den Materialized View.

Dies sind nur einige Beispiele aus der langen Liste von Neuerungen, die in die neue PostgreSQL® Version Einzug gehalten haben. Mit JSON, Verbesserungen in Streaming Replication und einigen Verbesserungen in der Konfiguration wie Shared Memory Nutzung sind noch viele andere Neuigkeiten hinzugekommen. Allen, die an detaillierten Ausführungen aller neuen Features interessiert sind, seien die Release Notes ans Herz gelegt. Für RedHat, CentOS, Scientific Linux und Fedora liegen RPM Pakete unter http://yum.postgresql.org bereit. Für Debian steht das PGAPT Repository zur Verfügung. Genaue Instruktionen findet man unter http://wiki.postgresql.org/wiki/Apt

Kategorien: PostgreSQL®
Tags: PostgreSQL®

BH

über den Autor

Bernd Helmle

Technischer Leiter Datenbanken

zur Person

Bernd Helmle arbeitet als Datenbankberater und -entwickler für die credativ GmbH, Deutschland. Er verfügt über umfassende Erfahrung in der PostgreSQL<sup>®</sup>-Administration, Hochverfügbarkeitslösungen und PostgreSQL<sup>®</sup>-Optimierung und Performance-Tuning. Außerdem war er an verschiedenen Migrationsprojekten von anderen Datenbanken zu PostgreSQL<sup>®</sup> beteiligt. Bernd Helmle entwickelte und betreut die Informix Foreign Data Wrapper Erweiterung für PostgreSQL<sup>®</sup>.

Beiträge ansehen


Beitrag teilen: