「トランザクションのシミュレート」の手法は、データが単一の操作での変更を効果的に集計するためにビューを使用できる場合うまくいきます。しかし、データやドキュメント構造によりそのようなことができない場合、いくつかの別々のステージで操作を実行することでマルチフェーズトランザクション処理を使用することができます。
この方法はビューに依存しませんが、ドキュメント構造と更新が、追加のドキュメント更新なしに処理する必要のあるような固まっているもしくは遅くなっているトランザクションがあるかどうかわかることを簡単にします。 ビューを使用し、変更の監視操作をすると、ビューインデックスが更新されている間トランザクション処理で長い待ち時間につながります。
この方法を使用するには、前の例と同様に取引記録を使用しますが、アップデート処理の各段階を記録する取引記録を使用してください。
同じように2つの口座レコードで始めると:
{ "type" : "account", "account" : "James", "value" : 100, "transactions" : [] }
レコードにはこのレコードの現在のアクティブなトランザクションすべての配列を含むtransactions
フィールドが明示的に含まれています。
他の口座の対応するレコードは:
{ "type" : "account", "account" : "Alice", "value" : 200, "transactions" : [] }
さて順番に次の操作を実行します:
取引情報を記録した新しい取引記録を作成します:
{ "type" : "transaction", "fromacct" : "Alice", "toacct" : "James", "value" : 100, "status" : "waiting" }
取引記録の主要部分は同じですが、違いはトランザクションの進捗状況を監視するためstatus
フィールドを使用することです。
トランザクションID、たとえば、transact_20120717163
を記録します。
'保留'のトランザクションドキュメントでstatus
フィールドの値をセットします:
{ "type" : "transaction", "fromacct" : "Alice", "toacct" : "James", "value" : 100, "status" : "pending" }
適切なビューを使用してpending
状態でのすべての取引記録を探します:
function(doc, meta) { if (doc.type && doc.status && doc.type == "transaction" && doc.status == "pending" ) { emit([doc.fromacct,doc.toacct], doc.value); } }
トランザクション情報でtoacct
に指定されているレコードを更新し、トランザクションがまだ保留状態であることを確認します:
{ "type" : "account", "account" : "Alice", "value" : 100, "transactions" : ["transact_20120717163"] }
他の口座で繰り返します:
{ "type" : "account", "account" : "James", "value" : 200, "transactions" : ["transact_20120717163"] }
取引記録を更新し、レコードが更新済みであるとマークします:
{ "type" : "transaction", "fromacct" : "Alice", "toacct" : "James", "value" : 100, "status" : "committed" }
適切なビューを使用して、committed
状態のすべての取引記録を探します:
function(doc, meta) { if (doc.type && doc.status && doc.type == "transaction" && doc.status == "committed" ) { emit([doc.fromacct, doc.toacct], doc.value); } }
トランザクションに記載されている送金元口座のレコードを更新し、トランザクションIDを削除します:
{ "type" : "account", "account" : "Alice", "value" : 100, "transactions" : [] }
他の口座で繰り返します:
{ "type" : "account", "account" : "James", "value" : 200, "transactions" : [] }
取引記録の状態を'done'に更新します。これは適用されていない、もしくはコメントされていないトランザクションを識別するために使用される2つのビューからトランザクションを削除します。
この処理では、複数のステップが必要とされますが、各ステップで特定の操作が行われたかどうかを識別することができます。
たとえば、取引記録が'pending'とマークされている場合、対応する口座レコードがトランザクションIDを含んでいなくても、レコードは更新される必要があります。口座レコードが単一の原子操作を使用して更新されるので、レコードが更新されたかどうかを判断することが簡単になります。
各ステップで定義されるビューにアクセスするためのスイープ処理はレコードが更新される必要があるかどうかを判断できるという結果になります。つまり、操作の失敗、トランザクションの記録、そして更新操作が適用されたかどうかがある場合も、戻しによる変更や取り消しができるようになっています。