チェーンコードおよびチャネル全体でのアトミック更新の実行
アトミック・トランザクションを使用して、複数のチャネルおよびチェーンコードにわたる複数のトランザクションをアトミックな方法で完了できます。
アトミック・トランザクションは、すべて成功するか、またはいずれも成功しない、分割できない一連のデータ操作です。
アトミック・トランザクションは、複数のチェーンコードが別々のチャネルにデプロイされる複雑な状況で役立ちます。アトミック・トランザクションを使用すると、複数のブロックチェーン・トランザクションの実行中にネットワークやシステムに障害が発生した場合でも、データの一貫性を維持できます。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とMarbles)を使用する次の例を考えてみます。Balance Transferサンプルは、アカウント残高間で資金を転送できる2つの当事者を表します。Marblesサンプルでは、marbleを作成し、所有者間で交換できます。Balance Transferチェーンコードで資金を交換し、Marblesチェーンコードでmarbleの所有権を変更することで、個々の(アトミックでない)トランザクションを使用してmarbleを購入できます。ただし、これらのトランザクションのいずれかでエラーが発生した場合、台帳は一貫性のない状態(資金は転送されたがmarbleは転送されなかった、またはmarbleは転送されたが支払われなかった)のままになる可能性があります。
このシナリオでは、アトミック・トランザクションをサポートするREST APIエンドポイントで既存のチェーンコードを使用できます。資金の交換とmarbleの所有権の移転は、両方とも成功するか、両方とも失敗である必要があります。いずれかのトランザクションでエラーが発生した場合、どちらのトランザクションもコミットされません。このシナリオを調べるには、次のステップを実行します:
- Balance TransferおよびMarblesサンプルを異なるチャネルにインストールします。サンプルをインストールする方法の詳細は、「サンプルを使用したOracle Blockchain Platformの確認」を参照してください。
- Marblesサンプルで、
Create a new marble
アクションを呼び出して、様々なmarbleの所有者に多数のmarbleを作成します。 Invoke Atomic Transaction
RESTエンドポイントを使用して、MarblesサンプルとBalance Transferサンプルの両方を呼び出すアトミック・トランザクションを完了します。
たとえば、次のトランザクションでは、marble1
というmarbleが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未満の場合、そのアカウントからお金は取られず、marbleはTomに転送されません。