楽観的ロックにパターン名がついていることを書籍で知りました。内容についてまとめておこうと思います。
アプリケーショントランザクションの管理
ここで説明する排他制御は、例えば以下のような一連のシーンにおける排他制御を指します。1,2 はそれぞれ異なるDBトランザクションにあることを想定しています。
- DBからデータを取得(SELECT文発行)
- データを更新(UPDATE文発行)
更新画面表示 → 更新データを入力 → 更新処理
みたいな流れがまさにそれです。
このような業務的にはひとかたまりの処理をDBトランザクションと区別して「アプリケーショントランザクション」と呼びます。
管理しないとどうなるか
次の場合を考えます。
- Aさんが商品Xのデータを表示(
price
: 1000) - Bさんが商品Xのデータを表示(
price
: 1000) - Aさんが商品Xのデータを更新(
price
: 1200) - Bさんが商品Xのデータを更新(
price
: 1500)
「アプリケーショントランザクション」を管理しない場合、最終的なテーブルの状態は、4.でBさんが更新したデータ(price
: 1500)になっています。つまり、Aさんによる更新処理はBさんによる更新処理で上書きされた状態です。
このような事象を「ロストアップデート」と呼び、業務上不整合を引き起こす可能性があります。
Version Number パターン
このような問題の回避策のひとつが「Version Number パターン」です。 Version Number パターンでは、テーブルに Version を管理するためのカラムを用意します。テーブルイメージは以下の通りです。
【product】
product_id | product_name | price | version |
---|---|---|---|
1001 | 商品X | 1000 | 0 |
1002 | 商品Y | 2000 | 0 |
更新時には、抽出条件としてデータ取得時のversion
の値を指定します。それと同時に、version
の値を1増加させます。price
を更新する場合を例に挙げると、最終的に発行される更新時のSQLは以下のようになります。
update product set product_name = n , price = p , version = version + 1 where product_id = '1001' and version = v ;
※ n: 取得時のproduct_name
、p: 更新時のprice
、v: 取得時のversion
以上が Version Number パターンによるアプリケーショントランザクションの管理方法になります。
活用した結果
先ほどと同じ例で、 Version Number パターンを活用した場合を考えてみます。
- Aさんが商品Xのデータを表示 → 成功(
price
: 1000,version
: 0) - Bさんが商品Xのデータを表示 → 成功(
price
: 1000,version
: 0) - Aさんが商品Xのデータを更新 → 成功(
price
: 1200,version
: 1) - Bさんが商品Xのデータを更新 → 失敗(レコードなし)
4.の更新処理を実施しても、既にversion
は 1 に更新済みのため、レコードが更新されることはありません。あとは適切なエラーメッセージを返してあげて、再度更新処理をしてもらえば問題を回避できます。