理系学生日記

おまえはいつまで学生気分なのか

PoEAA: Optimistic Offline Lock

今日からは Offline Concurrency Patterns ということで、排他制御の話に入ってきます。今日は、Optimistic Offline Lock ということで、楽観的排他制御です。

Optimistic Offline Lock は、コミットしようとしているデータ変更が他のセッションでの変更と競合しないことを確認することで不整合を回避するパターンです。 Pessimistic Offline Lock が、競合の頻度が高いケースを想定している一方で、Optimistic Offline Lock はその競合頻度が低いことを想定しています。

Optimistic Offline Lock は、セッションが特定レコードをロードしてから、他のセッションが当該レコードを変更していないことを確認するというものです。よく見られる実装としては、個々のレコードに対してバージョン番号を付与するというものがあります。 レコードを変更するタイミングでバージョン番号をインクリメントすることをルール化しておくことができれば、Optimistic Offline Lock はレコードデータを変更するタイミングにおける当該レコードのバージョンと、セッションに保持しているデータのバージョンが一致していることを確認することと同義になります。 RDBMS をデータストアとすれば、以下のようにしてこのパターンを実現することができます。

  1. UPDATE や DELETE 文といったデータ変更を行う SQL の criteria にバージョン番号を付与する
  2. SQL で変更が起こったレコード数を比較し、(SQL の意図する変更レコード数が 1 の場合)0 件の場合は、他のセッションがデータを更新していた

バージョン番号だけでなく、更新者や更新時刻を使用することができます。この場合、「いつ」「誰が」そのレコードを(自分以外で)更新したのかといった情報を提示することができます。ただし、この場合は時刻の粒度には気をつける必要があります。

Optimistic Offline Lock では、読取りの一貫性(inconsistent read) の検知ができない点には気をつける必要があります。例えば、今年度の住民税を計算・更新するには、現在の住所をベースにする必要がありますが、住民税を計算するセッションと住所を更新するセッションが競合した場合、住民税を計算するセッションはなかなか住所の更新競合が発生していることに気付きにくいという問題です。 こういった場合は、Coarse-Grained Lock の方が望ましい場合も多くでてくるでしょう。