Die 2 Sitzungen sollten wie folgt aussehen:
user = Student.query.with_for_update(of=Student, nowait=True).filter(Student.id == 122).first()
user.type = 1
db.session.commit()
und
user = Student.query.with_for_update(of=Student, nowait=True).filter(Student.id == 122).first()
user.type -= 1
db.session.commit()
Für FOR UPDATE
richtig funktionieren, alle Beteiligte Transaktionen, die die Zeile aktualisieren möchten, müssen sie verwenden.
In Ihrem Beispiel verwendet Sitzung 2 with_for_update
nicht . Da Sie ihm nicht gesagt haben, dass es FOR UPDATE
verwenden soll , ist es frei, den alten Wert der Zeile zu lesen (da der neue Wert noch nicht festgeschrieben wurde und Sperren keine reinen Leser blockieren), dann diesen In-Memory-Wert zu ändern und ihn dann zurückzuschreiben.
Wenn Sie FOR UPDATE
nicht verwenden möchten Überall dort, wo Sie row mit der Absicht lesen, sie zu ändern, könnten Sie stattdessen isolation level serializable
verwenden überall, überallhin, allerorts. Wenn Sie dies jedoch tun, blockieren die Dinge möglicherweise nicht, sondern scheinen bis zum Commit erfolgreich zu sein, und werfen dann Serialisierungsfehler aus, die abgefangen und behandelt werden müssen.
Hinweis: Ihr Vorbearbeitungsbeispiel hätte funktionieren müssen, da beide Sitzungen mit with_for_update
gekennzeichnet waren .