InhaltsverzeichnisKlicke auf den Link, um zur gewünschten Stelle zu navigieren
Dieser Inhalt wurde automatisch aus dem Ukrainischen übersetzt.
Wenn Sie mit Rails arbeiten und gleichzeitig eine Änderung eines Datensatzes durch mehrere Prozesse vermeiden müssen, sollten Sie auf den Mechanismus der Datensatzsperrung in der Datenbank achten. Eine der zuverlässigsten Methoden, dies zu tun, ist pessimistische Sperrung.
Was ist eine pessimistische Sperre?
Eine pessimistische Sperre bedeutet, dass der Datensatz in der Datenbank physisch für Änderungen von anderen Threads oder Prozessen blockiert wird, bis die aktuelle Operation abgeschlossen ist. Das heißt, wenn ein Prozess eine Sperre auf den Datensatz erhalten hat, müssen die anderen warten, bis er sie freigibt.
In ActiveRecord wird die pessimistische Sperrung durch die Methode lock implementiert, die SELECT ... FOR UPDATE hinzufügt, die die Sperre bis zum Ende der Transaktion hält.
Verwendung in Rails
Hier ist ein einfaches Beispiel für die Verwendung von lock in Rails:
ActiveRecord::Base.transaction do order = Order.lock.find(order_id) order.status = "processed" order.save! end
In diesem Fall, wenn ein anderer Prozess versucht, die Bestellung mit derselben order_id zu erhalten, muss er warten, bis der aktuelle Prozess die Transaktion abgeschlossen hat.
Warum ist das notwendig?
Stellen wir uns vor, wir bearbeiten Bestellungen. Wenn der Benutzer auf die Schaltfläche "Bezahlen" klickt, müssen wir die Menge des Produkts im Lager verringern. Wenn mehrere Personen gleichzeitig versuchen, die letzte Einheit des Produkts zu kaufen, kann ohne Sperrung ein Race Condition auftreten:
- Prozess 1 liest die Menge des Produkts (1 Einheit).
- Prozess 2 liest dieselbe Menge (1 Einheit).
- Beide Prozesse versuchen, den neuen Wert (0 Einheiten) zu schreiben.
- Einer der Prozesse verliert das Update des anderen.
Wenn jedoch lock verwendet wird, muss der zweite Prozess warten, bis der erste abgeschlossen ist, bevor er entscheidet, was zu tun ist.
Alternativen zur pessimistischen Sperre
Pessimistische Sperrung ist nicht immer die beste Wahl, da sie andere Prozesse blockieren kann und die Leistung der Anwendung verlangsamt. Manchmal ist es besser,:
- Optimistische Sperrung — überprüft, ob sich der Datensatz zwischen Lesen und Schreiben geändert hat.
- Atomare Operationen — verwendet UPDATE ... WHERE oder increment! ohne Werte in Ruby zu lesen.
- Warteschlangenbasierter Ansatz — verteilt Updates über eine Warteschlange (Sidekiq, RabbitMQ).
Optimistische Sperrung in Rails
Optimistische Sperrung funktioniert über die Spalte lock_version. Wenn zwei Prozesse einen Datensatz lesen, überprüft das System beim Versuch, Änderungen zu schreiben, ob sich der Datensatz in der Zwischenzeit geändert hat:
class Order < ApplicationRecord attr_accessor :lock_version end
Wenn dann ein Prozess Änderungen vornimmt und ein anderer versucht, eine veraltete Version zu schreiben, erhält er ActiveRecord::StaleObjectError.
Einfach gesagt:
- Pessimistische Sperrung blockiert den Datensatz, um Konflikte zu vermeiden.
- Optimistische Sperrung ermöglicht das Arbeiten ohne Sperrung, erfordert jedoch die Behandlung von Konflikten.
- Atomare Operationen verringern das Risiko von Race Conditions ohne Sperrungen.
Wählen Sie den richtigen Ansatz je nach Aufgabe. Wenn es kritisch ist, Konflikte um jeden Preis zu vermeiden — verwenden Sie lock. Wenn die Leistung wichtig ist und Konflikte toleriert werden können — ist lock_version oder atomare Updates besser.
Dieser Beitrag hat noch keine Ergänzungen vom Autor.