チェーンコードおよびチャネル全体でのアトミック更新の実行
原子性トランザクションを使用して、複数のチャネルおよびチェーンコードにわたる複数のトランザクションを原子的な方法で完了できます。
アトミック・トランザクションは、すべて成功するか、またはいずれも成功しない、分割できない一連のデータ操作です。
原子性トランザクションは、複数のチェーンコードが別々のチャネルにデプロイされる複雑な状況で役立ちます。原子性トランザクションを使用して、ネットワークまたはシステム障害が発生した場合でも、複数のブロックチェーン・トランザクションの実行中にデータの一貫性を維持できます。Oracle Blockchain Platformでは、2フェーズ・コミット・プロトコルを使用して原子性トランザクションがサポートされます。このプロトコルでは、各データ操作が準備される初期フェーズの後に、各データ操作が実際にコミットされるフェーズが続きます。
restproxy/api/v2/atomicTransactions
各原子性トランザクションは、2つ以上のブロックチェーン・トランザクションで構成されます。原子性トランザクションの結果(returnCode
値)は、Success
またはFailure
です。原子性トランザクションでは、リクエストされた各ブロックチェーン・トランザクションは、準備フェーズとコミットまたはロールバック・フェーズの2つの異なる操作に分割されます。
- 準備フェーズでは、各トランザクションは通常どおり承認されますが、最終決定されるのではなく、変更がステージングされ、他のトランザクションでステージングされた値が変更されないように値がロックされます。
- ブロックチェーン・トランザクションごとに準備フェーズが成功した場合、トランザクションは組込みチェーンコードを使用して承認およびコミットされます。以前にロックされた値はロック解除され、アトミック・トランザクションの結果は
Success
です。 - ブロックチェーン・トランザクションに対して準備フェーズが失敗した場合、準備フェーズが成功した他のすべてのトランザクションは、組込みチェーンコードを使用して再度ロールバックされます。ステージングされた変更は削除され、以前にロックされた値はロック解除されます。アトミック・トランザクションの結果は
Failure
です。
- アトミック・トランザクションはまだ準備フェーズにあり、準備されたトランザクションによってロックされたキーの変更が別のトランザクションによって試行されます。この場合、システムは設計どおりに動作します。このエラーが発生する場合は、2番目のトランザクションを再試行してください。これは、アプリケーションがファントム読取りエラーまたはマルチバージョン同時実行性制御(MVCC)エラーを処理する方法に似ています。
- 原子性トランザクションによって返される
GlobalStatus
値はHeuristicOutcome
です。この場合、コミット操作の1つが失敗したため、アトミック・トランザクション操作が取り消されました。これはまれに発生するため、手動で解決する必要がある場合があります。ヒューリスティックな結果の1つの副作用として、コミットまたはロールバックに失敗したトランザクションによって一部のキーがロックされたままになることがあります。この場合、次のREST APIエンドポイントを使用して、アトミック・トランザクションのロックを解除します。restproxy/api/v2/atomicTransactions/{globalTransactionId}
シナリオ: サンプルを使用した原子性トランザクションの確認
Oracle Blockchain Platformに含まれる2つのサンプル・チェーンコード(残高転送と大理石)を使用する次の例を考えてみます。Balance Transferサンプルは、勘定科目残高間で資金を転送できる2つのパーティを表します。Marblesサンプルを使用すると、大理石を作成し、所有者間で交換できます。残高転送チェーンコードで資金を交換し、Marblesチェーンコードで大理石の所有権を変更することで、個人(非原子性)トランザクションを使用して大理石を購入できます。ただし、これらのトランザクションのいずれかでエラーが発生した場合、元帳は一貫性のない状態のままになる可能性があります。つまり、資金は転送されたが大理石は転送されなかったか、大理石は転送されたが支払われなかったかのいずれかです。
このシナリオでは、原子性トランザクションをサポートするREST APIエンドポイントで既存のチェーンコードを使用できます。資金の交換と大理石の所有権の移転は、両方とも成功するか、両方とも失敗しなければなりません。いずれかのトランザクションでエラーが発生した場合、どちらのトランザクションもコミットされません。このシナリオを調べるには、次のステップを実行します。
- 残高転送および大理石のサンプルを異なるチャネルにインストールします。サンプルをインストールする方法の詳細は、「サンプルを使用したOracle Blockchain Platformの確認」を参照してください。
- Marblesサンプルで、
Create a new marble
アクションを起動して、様々な大理石の所有者に多数の大理石を作成します。 Invoke Atomic Transaction
RESTエンドポイントを使用して、MarblesサンプルとBalance Transferサンプルの両方を起動する原子性トランザクションを完了します。
たとえば、次のトランザクションでは、marble1
という大理石がTomに転送され、アカウントaからアカウントbに50コインが送信されます。
{
"transactions": [
{"chaincode":"obcs-marbles","args":["transferMarble", "marble1", "tom"],"timeout":0, "channel":"goods"},
{"chaincode":"obcs-example02","args":["invoke", "a", "b", "50"],"timeout":0, "channel":"wallet"}
],
"isolationLevel": "serializable",
"prepareTimeout": 10000,
"sync": true
}
前のトランザクションで、両方のトランザクションが準備フェーズで成功した場合は、両方のトランザクションが元帳にコミットされます。いずれかのトランザクションでエラーが発生した場合、2番目のフェーズではトランザクションはコミットされません。かわりに、両方のトランザクションがロールバックされます。たとえば、アカウントaにコインが50未満の場合、そのアカウントからお金は取られず、大理石はTomに転送されません。