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

Sperren Sie für SELECT, damit ein anderer Prozess keine alten Daten erhält

Ihre Frage bezieht sich auf eine unbekannte Quelle:

Ich habe mir das Sperren von Zeilen angesehen, aber es heißt, Sie können selectstatements nicht verhindern, was so klingt, als würde es für meine Bedingung hier nicht funktionieren. Ist meine einzige Option, Beratungssperren zu verwenden?

Die offizielle Dokumentation zu diesem Thema:

Sperren auf Zeilenebene wirken sich nicht auf die Datenabfrage aus; sie blockieren nur Schreiber und Schließfächer in dieselbe Zeile.

Gleichzeitige Versuche werden nicht nur auswählen, sondern versuchen, dieselbe Sperre auf Zeilenebene mit SELECT ... FOR UPDATE aufzuheben - was dazu führt, dass sie darauf warten, dass eine vorherige Transaktion, die eine Sperre für dieselbe Zeile hält, entweder festgeschrieben oder rückgängig gemacht wird. Genau das, was Sie wollten.

Allerdings , lassen sich viele Anwendungsfälle besser mit Beratungssperren lösen - in Versionen vor 9.5. Sie können Zeilen, die verarbeitet werden, weiterhin mit FOR UPDATE sperren zusätzlich zur Sicherheit. Aber wenn die nächste Transaktion nur "die nächste freie Zeile" verarbeiten will, ist das oft viel Es ist effizienter, nicht auf dieselbe Zeile zu warten, die mit ziemlicher Sicherheit nicht verfügbar ist, nachdem die Sperre aufgehoben wurde, sondern sofort zur "nächsten freien" Zeile zu springen.

Berücksichtigen Sie in Postgres 9.5+ FOR UPDATE SKIP LOCKED dafür. Wie @Craig kommentierte, kann dies Beratungssperren weitgehend ersetzen.

Verwandte Frage, die über das gleiche Leistungsschwein stolpert:

  • Funktion dauert ewig, um für eine große Anzahl von Datensätzen ausgeführt zu werden

Erklärung und Codebeispiel für Hinweissperren oder FOR UPDATE SKIP LOCKED in Postgres 9.5+:

  • Postgres-UPDATE ... LIMIT 1

Um viele Zeilen gleichzeitig zu sperren :

  • So markieren Sie eine bestimmte Anzahl von Zeilen in einer Tabelle bei gleichzeitigem Zugriff