De 2 sessioner skal se sådan ud:
user = Student.query.with_for_update(of=Student, nowait=True).filter(Student.id == 122).first()
user.type = 1
db.session.commit()
og
user = Student.query.with_for_update(of=Student, nowait=True).filter(Student.id == 122).first()
user.type -= 1
db.session.commit()
For at FOR UPDATE
for at fungere korrekt, alle involverede transaktioner, der har til hensigt at opdatere rækken, skal bruge den.
I dit eksempel bruger session 2 ikke with_for_update
. Da du ikke fortalte den at bruge FOR UPDATE
, er det gratis at læse den gamle værdi af rækken (da den nye værdi endnu ikke er blevet commited, og låse ikke blokerer rene læsere), så ændre den i hukommelsesværdien, og skriv den derefter tilbage.
Hvis du ikke ønsker at bruge FOR UPDATE
overalt hvor du læser rækken med den hensigt at ændre den, kan du i stedet bruge isolation level serializable
overalt. Men hvis du gør det, blokerer tingene muligvis ikke, men vil snarere se ud til at lykkes, indtil commit, og derefter smide serialiseringsfejl, der skal fanges og håndteres.
Bemærk: Dit forhåndsredigeringseksempel burde have fungeret, da begge sessioner var mærket med with_for_update
.