Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Zeile einfügen und Race-Condition vermeiden (PHP/MySQL)

Normalerweise beinhaltet die Lösung für solche Parallelitätsprobleme Transaktionen und optimistisches Sperren :Wenn Sie den Zähler aktualisieren, fügen Sie ein where hinzu -Klausel, um den alten Wert zu prüfen und die Anzahl der aktualisierten Zeilen zu zählen.

v = select value from counter where id=x.
update counter set value = v+1 where value = v and id=x

Wenn der Zähler in der Zwischenzeit aktualisiert wurde, ändert die Aktualisierung keine Zeile – Sie wissen also, dass Sie die Transaktion rückgängig machen und noch einmal versuchen müssen.

Ein Problem besteht darin, dass dies zu einer hohen Konkurrenz führen könnte , mit nur wenigen Transaktionen, die erfolgreich sind, und vielen, die fehlschlagen.

Dann ist es vielleicht besser, beim pessimistischen Sperren zu bleiben , wo Sie die Zeile zuerst sperren und dann aktualisieren. Aber nur ein Benchmark wird es Ihnen sagen.

BEARBEITEN

Wenn Sie eine Transaktion ohne optimistisches Sperren verwenden, könnte das folgende Szenario eintreten.

Max authorized = 50. Current value = 49.

T1: start tx, read value --> 49
T2: start tx, read value --> 49
T1: update value --> 50, acquire a row lock
T1: commits --> release the lock
T2: update value --> 50, acquire a row lock
T2: commits --> release the lock

Beide Transaktionen sind erfolgreich, der Wert ist 50, aber es gibt eine Inkonsistenz.