「トランザクションの3つの方式」にて
キューイング方式では、トランザクションの最後で1回しか実際の変更を試みません。失敗か成功かは楽観的並行性制御により判断すればいいでしょう。
と書きました。楽観的並行性制御とは、複数の並行プロセスからの変更要求を処理する方式のひとつです。簡単軽量な点がメリットです。楽観的ロックと呼ばれることもありますが、実際にロックすることはありません。
データベースのひとつのレコードを取得してそれを変更する状況で考えます。前提として、レコードの変更を検出するための値が必要です。例えば、レコードの最終変更時刻、変更ごとにインクリメントされるリビジョン番号、あるいはデータ内容に関するダイジェスト値などです。データの変更に伴って変わる値なら何でもかまいません。以下の説明では、変更検出にリビジョン番号を使うとします。
下の絵で、左がデータベースサーバー、右がクライアントです。まず、変更が成功するシナリオです。サーバーは、もとのレコードのリビジョン番号(例では8)とクライアントが送ってきたリビジョン番号を比較して、等しかったらレコードの更新とリビジョン番号のインクリメントをします
このとき、サーバー側で行われる「リビジョン番号の比較、レコードの更新、リビジョン番号のインクリメント」という一連の処理は分割不可能です。ここだけは原子的であることが要求されます。
リビジョン番号が異なっているときは、他の誰かが変更したので、更新は失敗します。
MongoDBの場合なら、次の解説が参考になります。
- アトミックな操作 → https://wiki.10gen.com/pages/viewpage.action?pageId=7209573
- Isolate Sequence of Operations → http://docs.mongodb.org/manual/tutorial/isolate-sequence-of-operations/
- Model Data for Atomic Operations → http://docs.mongodb.org/manual/tutorial/model-data-for-atomic-operations/