2つのセッションは次のようになります。
user = Student.query.with_for_update(of=Student, nowait=True).filter(Student.id == 122).first()
user.type = 1
db.session.commit()
および
user = Student.query.with_for_update(of=Student, nowait=True).filter(Student.id == 122).first()
user.type -= 1
db.session.commit()
FOR UPDATE
の場合 正しく機能するには、すべて 行を更新する予定の関連トランザクションは、それを使用する必要があります。
あなたの例では、セッション2はwith_for_update
を使用していません 。 FOR UPDATE
を使用するように指示しなかったため 、行の古い値を自由に読み取って(新しい値はまだコミットされておらず、ロックは純粋なリーダーをブロックしないため)、そのメモリ内の値を変更して、書き戻すことができます。
FOR UPDATE
を使用したくない場合 行を変更する意図で読み取るすべての場所で、代わりにisolation level serializable
を使用できます。 どこにでも。ただし、そうすると、ブロックされない可能性がありますが、コミットするまで成功したように見え、その後、キャッチして処理する必要があるシリアル化エラーをスローします。
注: 両方のセッションがwith_for_update
でラベル付けされているため、事前編集の例は機能しているはずです。 。