PoEAA ch16 Coarse-Grained Lock
Coarse-Grained Lock
Locks a set of related objects with a single lock.
- オブジェクトはグループとして編集される
- 例: 顧客と住所
- グループを構成する1要素を編集する際には、グループ全体をロックするのが理にかなっている
- 各要素別々にロックを管理するのは多くの困難をともなう
- 全要素検索してロックしなければならない
- 「顧客と住所」くらいなら問題ないが、オブジェクトグラフが大きくなってくると困難
- Optimistic Offline Lockの場合
- ロックのために全要素読み込まないといけない
- レコードにバージョンが紐付いているため
- 読まなくてもよいレコードも読んでしまいい、パフォーマンスに悪影響
- ロックのために全要素読み込まないといけない
- Pessimistic Offline Lockの場合
- 管理が大変
- ロックテーブルにアクセス集中し競合が発生する
- 全要素検索してロックしなければならない
- Coarse-Grained Lockでは、単一のロックで多数のオブジェクトをロックする
- ロック操作の簡略化
- ロックのために全レコード読み込まなくて良い
How It Works
- Optimistic Offline Lockの場合
- shared lock
- グループ内の全オブジェクトは同一のバージョンオブジェクトを参照するようにする
- 同じ値ではなく、同一のバージョンを参照
- 共通のバージョンをインクリメントすることで、グループ全体がロックされる
- グループ内の全オブジェクトは同一のバージョンオブジェクトを参照するようにする
- shared lock
- Pessimistic Offline Lockの場合
- なにがしかのlockable tokenをグループ内の全オブジェクトで共有
- Optimistic Offline Lockパターンの「共通のバージョン」はまさにlockable tokenとして利用できる
- Evansの「Aggregate」
- root
- オブジェクトグラフのroot
- boundary
- Aggregateに含まれるオブジェクトと外との境界
- boundary内部のオブジェクトには、root経由でのみアクセスできる
- rootをロックすることで、Aggregateを構成する全オブジェクトをロックしたことにする
- Aggregateを構成する各オブジェクトからrootへのアクセスはどうする
- rootへの直接参照を保持する
- 親をrootまでたどる
- オブジェクトグラフが巨大な場合、パフォーマンスに悪影響
- Lazy Loadの併用
- 親オブジェクトを完全にロードしなくてもよいよう
- 無限ループ回避
- Lazy Loadの問題
- Inconsistent Readのおそれ
- 別々のシステムトランザクションでデータ読み取りが行われるため
- Inconsistent Readのおそれ
- Lazy Loadの併用
- オブジェクトグラフが巨大な場合、パフォーマンスに悪影響
- 実装の選定
- root lock
- rootのみロックする
- メリデメ
- メリ
- root以外、バージョンテーブルとのjoin不要
- デメ
- rootまで親オブジェクトをたどる際に読み込み負荷がある
- Lazy Loadで回避できるが、Inconsistent Readがおきる
- rootまで親オブジェクトをたどる際に読み込み負荷がある
- メリ
- shared lock (Optimistic Offline Lock)
- Aggregateを構成する任意のオブジェクトをロックすると、root含め全オブジェクトがロックされる
- メリデメ
- メリ
- rootまで親をたどらなくてよい
- デメ
- ほぼすべてのSELECT文でバージョンテーブルとのjoinが必要
- メリ
- Pessimistic Offline Lock
- ヘンな組み合わせ
- root lock
- root
When to Use It
- 機能要件
- ビジネス要件
- 例: 「貸出」と「機材」
- あるユーザが貸出を編集しているとき、別のユーザが同時に機材を編集できてはいけない
- 例: 「貸出」と「機材」
- ビジネス要件
- 非機能要件
- パフォーマンス
- ロックの獲得・解放が低コストになる
- パフォーマンス
- オブジェクト間に不自然な関連を追加してしまうことに留意する
- 双方向参照
- rootへの直接参照