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?
Verwenden Sie das explizite Sperren auf Zeilenebene in sortierten Unterabfragen in allen konkurrierenden Abfragen . (Simple SELECT
konkurriert nicht.)
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.
Tags und Links database postgresql concurrency deadlock database-deadlocks