PoEAA ch16 Optimistic Offline Lock

PoEAAデザインパターン勉強メモ

出典: 


【補】用語

  • セッションとビジネストランザクションがほぼ同義扱い

Optimistic Offline Lock

Prevents conflicts between concurrent busines transactions by detecting a conflict and rolling back the transaction.

  • ビジネストランザクションは複数のシステムトランザクションにわたることがしばしば
  • 単一のシステムトランザクション境界の外に出ると、レコードデータの一貫性の担保はRDBMS任せとはいかなくなる

    • lost update

      • 複数のセッションから同一のデータを更新
    • inconsistent read

      • あるセッションがデータを変更しているとき別のセッションから読み出し
  • Optimistic Offline Lockによる解決

    • ビジネストランザクションのcommit前に、他のセッションによる変更とぶつからないか検証
    • ぶつかってなければシステムトランザクションのロックを取得してUPDATEする
  • Pessimistic Offline Lockとの比較

    • Optimistic-は、「衝突可能性は低い」という過程に基づく

      • 複数ユーザが同じデータを同時に触れるようにする

        • VCSとかがこの類
    • cf. Pessimistic-は「衝突可能性が高い」という過程に基づく

      • 同じデータを同時に触れるのは1ユーザのみ

How It Works

  • あるセッションがレコードデータを読み出して依頼、別のセッションが変更を加えていないことを検証してロックを取得する

    • システムトランザクションの中で取得したもののみが、そのシステムトランザクションの中でのみ有効
  • 実装方法

    • 最もよくある方法: レコードにversionカラムを追加

      • 流れ

        1. Optimistic Offline Lock取得時、version値が変わっていないことを検証

          • 変わっていたらロック取得させない
        2. ロック取得して、レコード更新時にインクリメント
      • 1つのSQL文でversionのインクリメントとロック取得を同時に行える

        1. WHERE version = :versionに対してSET version = :version + 1

          • DELETE文でも同様
        2. 更新行数が返ってくるので、ロック取得判定に用いる

          • 1: 成功、ロック取得
          • 0: 失敗

            • abort
            • 衝突解消してリトライ
      • ユーザーに更新失敗を通知するために、「誰が」「いつ」更新をかけたかの情報も保持するのは有用

        • 「いつ」をバージョン番号の代わりに用いるのはNG

          • 信頼がおけない

            • とくに複数サーバが協調動作しているとき
    • 別解

      • WHERE句で全フイールド見る

        • メリ

          • バージョンフィールド不要
        • デメ

          • UPDATE文が複雑に
          • パフォーマンス問題

            • インデックスうまく効かなかったりする
  • versionフィールドを持つ方法では、必ずしもinconsistent readを防げない

    • 例: 料金の税計算が顧客住所に依存するケース

      • 料金レコードのversionを検証することで、他のセッションにより変更されていないことを担保できる
      • が、住所レコードが変更されると税計算ロジックが変わり、inconsistent readがおきる
      • この例では、住所レコードのバージョンチェックも必要
  • versionカラムを再読み込みしてconsistent readであることをチェックできるためには、トランザクション分離レベルがrepeatable read以上であること

    • 【補】unrepeatable read以下だと、同じversionカラムを読んでいるのに、他のシステムトランザクションのcommitが反映されて値が変わってしまう
  • 並列性の向上

    • inconsistent read問題を防ぐためにversionカラムを使用するのは大げさなこともある
      • トランザクションが、行の存在にのみ依存する場合
      • トランザクションが、ある1フィールドにのみ依存する場合
    • versionカラムではなく、上記の条件で「衝突」判定することで並列性を向上
  • Coarse-Grained Lock

    • オブジェクトをグループ化して、単一のロック対象として扱う
  • ドメインを知ること

    • 本当に衝突はおきるのか?
    • 税計算にいつ時点の住所を使うの?
    • 複数のセッションで同時にアイテム追加していいの?
  • VCS: 身近なOptimistic Offline Lockの例
  • VCSのアナロジー: ビジネスデータのマージ
  • 衝突の早期検出

    • 「衝突していない」ことの検出は、ビジネストランザクション内の最後のシステムトランザクションの中でしかわからない
    • 「衝突している」ことはもっと早期にわかる
    • トランザクションの失敗が早期にわかると、複雑性を回避できることがあり有用

When to Use It

  • 衝突可能性の低いときに適する

    • 衝突したらrollbackか衝突解決

      • 衝突可能性が高い場合はユーザビリティ悪い
  • Pessimistic Offline Lockより実装が簡単
  • Pessimistic Offline Lockとは相補的
  • 衝突を最小限にしつつ並列アクセスを最大化するのが正しいアプローチ

    • 【補】Optimistic/Pessimisticをうまく併用しろということか

英語

  • confine

    • verb: 閉じ込める
    • noun: 境界

      • 文中では、トランザクション境界のこと
  • conundrum

    • なぞなぞ
  • unto

    • toに同じ

      • ただし不定詞の前につかない