仕事でこの辺りのちょっと踏み込んだ議論があったので、他のパターンを飛ばして先にOffline Concurrency Patternsやります。
概要
概要
- 競合を検出してロールバックさせることで、複数トランザクション間の競合をふせぐパターン。
- いわゆる楽観的排他制御・楽観的同時実行制御と言われているもの。
- 競合が滅多に発生しない場合に使われるパターン。競合が頻発する状況では、ビジネストランザクションのロールバックが頻発し、ユーザビリティを損なう。
- SCM(CVSやSubversion)は、Optimistic Offline Lockの代表的な実装例。マージの対象はソースコードのみなのでシンプルだが、業務システムでもマージ処理を実装することは可能、らしい。
- バージョンチェック方法としては、UPDATE分のWHERE句でVERSION列を指定する方法が基本。事前にVERSION列を取得して照合することもできるが、SELECT ~ FOR UPDATEで明示的に排他ロックを取得するか、トランザクション分離レベルとREPEATABLE_READかSERIALIZABLEにする必要がある(OracleやSQL Server2005では、スナップショット分離レベルでもOK)。
- WHERE句の条件に全カラムの値を指定する方法もあるが、VERSION列が不要になるかわりにWHERE句が複雑になる。DB実装によってはパフォーマンスの問題が発生する可能性もあるので考えて使う必要あり。
- UPDATE/DELTE文によるバージョンチェックだけでは、更新しない場合に対処できず、問題が発生するケースがある。たとえば、読み取ったデータをもとに計算をするような場合、読み取り元データの一貫性が必要となるケースがある。このような場合も、対象データをVERSION列で管理することが必要となることに注意。
- 同時実効制御が必要な場面では、まずはこちらを選択肢に上げる。理由は、並列処理性能が比較的高い点や、実装が容易な点。
- ビジネストランザクションの終了時まで競合検出を遅延させるため、システムの並列処理性能を比較的損ないづらい。競合した場合には、ビジネストランザクションをすべてロールバックする必要がある。
- ビジネストランザクションのロールバックコストが非常に高い場合には、使用は困難。そのようなケースではPessimistic Offline Lockを使う。
コメント