PoEAA ch16 Pessimistic Offline Lock

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

出典: 


Pessimistic Offline Lock

Prevents conflicts between concurrent business transactions by allowing only one business transaction at a time to access data.

  • ビジネストランザクションは複数のシステムトランザクションにわたる

    • 丸ごとシステムトランザクションで包むのは必ずしもうまくいかない

      • システムトランザクションは長時間開くように作られていない
  • まずはOptimistic Offline Lockを検討せよ
  • Optimisitic Offline Lockの問題点: 変更が衝突しうる

    • 変更を捨てる「犠牲者」が出るということ
    • 長いビジネストランザクションの最後に失敗して、作業が無駄になる
    • ほどなくそのシステムは使われなくなる
  • 上記が問題となる場合、Pessimistic Offline Lockを検討する

    • 衝突を予防する

      • ビジネストランザクションで必要なロックを、あらかじめすべて獲得する
      • 「不渡り」になることがない

How It Works

  • Pessimistic Offline Lockの実装は3段階

    1. ロックの種類を決める
    2. ロックマネージャを実装する
    3. ロックの利用の流れを定義する
  • ロックの種類

    • exclusive write lock

      • トランザクション中は、他からは書き込み不能、読み取りのみ可能
      • 参照系が最新データを読み取れる保証なし
    • exclusive read lock

      • 参照系でも常に最新のデータを読み取りたい場合はこれ
      • トランザクション中は、他からは読み取りも許さない
      • 並列性は深刻に損なわれる

        • たいていはexclusive write lockで十分
    • read/write lock

      • 合わせ技
      • はじめexclusive read lock
      • 同時利用数が増えてきたらexclusive write lockに緩和
  • readerセッションが複数あるのはOK

    • read lockを誰かが取得したら誰も変更できないため
    • 並列度を上げるのに寄与
  • ロックの種類の理解の重要性

    • システムの並列度を最大化し、ビジネス要件を満たし、複雑性を最小化する
    • ドメインモデラーや分析者も理解しなければならないもの

      • 純粋な技術の話ではなく、ドメインに跳ねる話だから
      • ゆえ、Domain Modelに含めるのは悪い考えではない

        • 【補】Data Source層寄りではなく、ということか
    • ロックの種類の選択をしくじると悲惨

      • 衝突を防げない
      • マルチユーザシステムなのに実質1人しか同時に触れない
      • ロッキング戦略のしくじりを実装で取り返すことはできない
  • ロックマネージャの実装

    • ビジネストランザクションからの要求に応じてロックの獲得・解放を行うか、これを拒否するモジュール
    • 知識

      • 何がロックされているか
      • ロックの所有者

        • ビジネストランザクションが、IDで一意に特定できる「モノ」ならばそれ
        • そうでない場合、ビジネストランザクションをロックマネージャーに渡すのは難しい
        • 代わりに「セッション」を渡す

          • セッション o-- ビジネストランザクションsの関係
    • 実装はシンプルに

      • ロックと所有者との対応表以上のものにしない

        • メモリ上のハッシュ表

          • Singletonにせよ
        • DB

          • クラスタリング構成のときに
  • ロックの利用の流れの定義

    • “protocol”

      • 何をロックする
      • いつロックする
      • いつ解放する
      • ロックを獲得できなかったときどうする
  • いつロックする

    • 基本的にはデータ取得前にロック獲得
    • しかし、ロック獲得はシステムトランザクションの中で行うので、トランザクション分離レベルがrepeatable以上なら実はいつでもいい

      • 楽観的にデータを先に取得し、その後にロック獲得してもいい
  • 何をロックする

    • PK
  • いつ解放する

    • 最も単純なのは、ビジネストランザクション完了時

      • 基本的にはこれを守る
      • パフォチューのためにやむなく早期解放したりもする
  • 獲得できなかったらどうする

    • abort
  • 「ロックと所有者との対応表」へのアクセスは直列でなければならない

    • DBの場合

      • システムトランザクションの中で獲得する
      • ロック対象IDカラムに一意性制約を課す
      • トランザクション分離レベルをserializableにすると究極に安全

        • serializableはパフォーマンス上問題になりうる
        • より低い分離レベルを使い分けることでこれを緩和する

          • ロック獲得のみserializable
          • ビジネストランザクションはより低い分離レベル
    • 直列アクセスがパフォーマンスのボトルネックになる場合は、ロックの粒度を考慮する

      • Coarse-Grained Lockの適用を検討する
  • デッドロック

    • Pessimistic Offline Lockはロックを獲得するのでデッドロックが起こりうる

      • 【補】cf. Optimistic Offline Lockは、名前に反してロックを獲得しないのでデッドロックは生じない
    • そもそもロックの獲得を待つのはナンセンス

      • ビジネストランザクションは長い
      • かりに、他のビジネストランザクションの完了を20分間待ってロック獲得できても誰も喜ばない
      • 獲得できなかった時点で即abortするほうがよい

        • シンプル
        • 待たないのでデッドロックが生じない

          • 【補】デッドロックはロックを「追加で獲得しに行く」から起こる
  • タイムアウトの考慮

    • ロックが解放されないままになるケース

      • クライアントマシンのクラッシュ
      • セッション放棄

        • Webアプリケーションではよくあること
    • アプリケーション側でタイムアウト制御を行うのではなく、アプリケーションサーバーで管理せよ

      • HTTPセッションがinvalidになったらロックを解放する
    • 別解: ロックにタイムスタンプを紐付けて、特定のageになったら解放する

When to Use It

  • 変更の衝突可能性が高いとき
  • 変更の衝突可能性が低くても、衝突時のコストが甚大なとき
  • Optimistic Offline Lockと相補的

    • 基本的にはOptimistic Offline Lockを使う
    • 本当に必要なときにのみPessimistic Offline Lockを使う
  • 単一のシステムトランザクションでビジネストランザクションを包むという選択肢

    • 決してよいものではない
    • が、条件によっては、Pessimistic Offline Lockと同程度の並列性に収まることがある

      • 実装はかなり簡単
    • 短い単一のシステムトランザクションに収まるなら、そうせよ

      • Offline Lock系パターンは使うな
  • RDBのロックの種類を知るとPessimistic Offline Lockの実装のためになる

    • 逆は成り立たない

英語

  • bounced

    • bounced check: 不渡り小切手
  • at the onset of

    • 〜のはじめに