Vermeiden von PostgreSQL-Deadlocks beim Ausführen von Massenaktualisierungs- und Löschvorgängen

9

Wir haben eine einzelne Tabelle, die keine Verweise auf andere Tabellen enthält.

%Vor%

Der Primärschlüssel der Tabelle ist eine Zusammensetzung aus id_A und id_B.

Das Lesen und Schreiben dieser Tabelle ist sehr parallel und die Tabelle hat Millionen von Zeilen. Wir haben mehrere gespeicherte Prozeduren, die Massenupdates durchführen und löschen. Diese gespeicherten Prozeduren werden gleichzeitig hauptsächlich durch Trigger und Anwendungscode aufgerufen.

Die Operationen sehen normalerweise so aus, als könnten sie tausende Datensätze zum Aktualisieren / Löschen abgleichen:

%Vor%

Es kommt zu Deadlocks und alle unsere Versuche, Operationen mit Sperren auszuführen (Zeilenebene mit SELECT FOR UPDATE und Sperren auf Tabellenebene) scheinen diese Deadlock-Probleme nicht zu lösen. (Beachten Sie, dass wir aufgrund der Auswirkungen auf die Leistung in keiner Weise Zugriff-exklusive Sperren für diese Tabelle verwenden können)

Gibt es einen anderen Weg, wie wir versuchen könnten, diese Deadlock-Situationen zu lösen? Das Referenzhandbuch sagt :

  

Die beste Verteidigung gegen Deadlocks besteht im Allgemeinen darin, sie zu vermeiden   Sicherstellen, dass alle Anwendungen, die eine Datenbank verwenden, Sperren erhalten   mehrere Objekte in einer konsistenten Reihenfolge.

Aber wie können wir das im obigen Szenario erreichen? Gibt es eine garantierte Möglichkeit, Bulk-update-Inset-Operationen in einer bestimmten Reihenfolge durchzuführen?

    
sanjayav 19.11.2014, 01:05
quelle

1 Antwort

10

Verwenden Sie das explizite Sperren auf Zeilenebene in sortierten Unterabfragen in allen konkurrierenden Abfragen . (Simple SELECT konkurriert nicht.)

LÖSCHEN

%Vor%

AKTUALISIEREN

%Vor%

Auf diese Weise werden Zeilen in der im Handbuch angegebenen Reihenfolge gesperrt.

Unter der Annahme, dass id_A , id_B niemals aktualisiert werden, können auch seltene Fallkomplikationen wie im Feld "Caution" im Handbuch ist nicht möglich.

Wenn Sie Schlüsselspalten nicht aktualisieren, können Sie den schwächeren Sperrmodus% co_de verwenden % Benötigt Postgres 9.3 oder höher.

Die andere Option ( langsam und sicher) ist die Verwendung von Serialisierbarer Isolationslevel für konkurrierende Transaktionen. Sie müssten sich auf Serialisierungsfehler vorbereiten. In diesem Fall müssen Sie den Befehl erneut versuchen.

    
Erwin Brandstetter 19.11.2014 11:33
quelle