Atomare Updates über Chaincodes und Kanäle hinweg vornehmen

Mit atomaren Transaktionen können Sie mehrere Transaktionen über Kanäle und Chaincodes hinweg atomar abschließen.

Eine atomare Transaktion ist eine unteilbare Reihe von Datenvorgängen, die entweder alle erfolgreich sind oder keine erfolgreich sind.

Atomare Transaktionen können in komplexen Situationen nützlich sein, in denen mehrere Chaincodes für separate Kanäle bereitgestellt werden. Sie können atomare Transaktionen verwenden, um die Datenkonsistenz bei der Ausführung mehrerer Blockchain-Transaktionen aufrechtzuerhalten, selbst wenn ein Netzwerk- oder Systemausfall auftritt. Oracle Blockchain Platform unterstützt atomare Transaktionen mit dem Zwei-Phasen-Commit-Protokoll. In einer ersten Phase, in der jeder Datenvorgang vorbereitet wird, folgt eine Phase, in der jeder Datenvorgang tatsächlich festgeschrieben wird.

Atomare Transaktionen funktionieren auf Anwendungsebene. Normalerweise müssen Sie die vorhandene Chaincode-Logik nicht ändern, um atomare Transaktionen zu unterstützen. Da ein oder mehrere zusätzliche Argumente vom Framework für atomare Transaktionen hinzugefügt werden, stellen Sie sicher, dass kein vorhandener Chaincode strenge Prüfungen der Anzahl der Argumente durchführt, die in der Chaincode-Methode übergeben werden. Atomare Transaktionen werden vom folgenden REST-API-Endpunkt unterstützt:
  • restproxy/api/v2/atomicTransactions
Der REST-API-Endpunkt bereitet die von Ihrem Chaincode definierten Transaktionen vor und verwendet dann integrierte Chaincodefunktionen, um entweder alle Transaktionen festzuschreiben oder alle Transaktionen zurückzusetzen, wenn während der Vorbereitungsphase Fehler auftreten. Weitere Informationen zu den REST-Endpunkten, mit denen atomare Transaktionen implementiert werden sollen, finden Sie unter REST-Endpunkte für atomare Transaktionen.

Jede atomare Transaktion besteht aus zwei oder mehr Blockchain-Transaktionen. Das Ergebnis (der returnCode-Wert) der atomaren Transaktion ist entweder Success oder Failure. In einer atomaren Transaktion wird jede angeforderte Blockchain-Transaktion in zwei verschiedene Vorgänge aufgeteilt: eine Vorbereitungsphase und dann entweder eine Commit- oder eine Rollback-Phase.

  • In der Vorbereitungsphase wird jede Transaktion wie gewohnt bestätigt. Anstatt jedoch abgeschlossen zu werden, werden die Änderungen zwischengespeichert und die Werte gesperrt, um zu verhindern, dass andere Transaktionen die zwischengespeicherten Werte ändern.
  • Wenn die Vorbereitungsphase für jede Blockchain-Transaktion erfolgreich ist, werden die Transaktionen mit integriertem Chaincode bestätigt und festgeschrieben. Die zuvor gesperrten Werte werden entsperrt, und das Ergebnis der atomaren Transaktion ist Success.
  • Wenn die Vorbereitungsphase für eine Blockchain-Transaktion nicht erfolgreich verläuft, werden alle anderen Transaktionen, bei denen die Vorbereitungsphase erfolgreich war, mit integriertem Chaincode zurückgesetzt. Die zwischengespeicherten Änderungen werden entfernt, und die zuvor gesperrten Werte werden entsperrt. Das Ergebnis der atomaren Transaktion ist Failure.
Da atomare Transaktionen durch Sperren von Schlüsseln funktionieren, erhalten Sie möglicherweise einen Two_Phase_Commit_Lock-Fehler, wenn eine andere Transaktion versucht, einen Schlüssel zu ändern, der durch eine derzeit aktive atomare Transaktion gesperrt ist, die vorbereitet wird. Dies kann in einem der folgenden beiden Szenarios auftreten:
  • Eine atomare Transaktion befindet sich noch in der vorbereiteten Phase, und eine andere Transaktion versucht, einen Schlüssel zu ändern, der durch die vorbereitete Transaktion gesperrt wurde. In diesem Fall arbeitet das System wie geplant. Wenn dieser Fehler auftritt, wiederholen Sie die zweite Transaktion. Dies entspricht der Art und Weise, wie Anwendungen Phantom-Lesefehler oder MVCC-(Multiversion Concurrency Control-)Fehler behandeln.
  • Der von der atomaren Transaktion zurückgegebene GlobalStatus-Wert ist HeuristicOutcome. In diesem Fall wurde ein atomarer Transaktionsvorgang abgebrochen, weil einer der Commit-Vorgänge nicht erfolgreich war. Dies ist ein seltenes Ereignis und muss möglicherweise manuell aufgelöst werden. Ein Nebeneffekt eines heuristischen Ergebnisses ist, dass einige Schlüssel möglicherweise durch Transaktionen gesperrt bleiben, die nicht festgeschrieben oder zurückgesetzt werden konnten. Verwenden Sie in diesem Fall den folgenden REST-API-Endpunkt, um die Sperre der atomaren Transaktion aufzuheben:
    • restproxy/api/v2/atomicTransactions/{globalTransactionId}
    Weitere Informationen zum REST-Endpunkt zum Entsperren atomarer Transaktionen finden Sie unter Atomare Transaktion entsperren.

Szenario: Atomare Transaktionen anhand von Beispielen untersuchen

Betrachten Sie das folgende Beispiel, das zwei der Beispielkettencodes verwendet, die in Oracle Blockchain Platform, Balance Transfer und Marbles enthalten sind. Die Probe "Saldotransfer" repräsentiert zwei Parteien mit der Möglichkeit, Mittel zwischen Kontensalden zu transferieren. Mit dem Marbles-Beispiel können Sie Murmeln erstellen und zwischen Eigentümern austauschen. Sie können einzelne (nichtatomare) Transaktionen verwenden, um einen Marmor zu kaufen, indem Sie Gelder im Balance Transfer-Kettencode austauschen und das Eigentum am Marmor im Marbles-Kettencode ändern. Wenn jedoch bei einer dieser Transaktionen ein Fehler auftritt, kann das Hauptbuch in einem inkonsistenten Zustand bleiben: Entweder wurden die Mittel übertragen, aber nicht der Marmor oder der Marmor wird übertragen, aber nicht bezahlt.

In diesem Szenario können Sie den vorhandenen Chaincode mit den REST-API-Endpunkten verwenden, die atomare Transaktionen unterstützen. Der Austausch von Geldern und der Eigentumsübergang des Marmors müssen erfolgreich sein oder beides scheitern. Wenn bei einer Transaktion ein Fehler auftritt, wird keine Transaktion festgeschrieben. Gehen Sie folgendermaßen vor, um dieses Szenario zu untersuchen:

  1. Installieren Sie die Balance Transfer- und Marbles-Proben auf verschiedenen Kanälen. Weitere Informationen zum Installieren der Beispiele finden Sie unter Oracle Blockchain Platform mit Beispielen kennenlernen.
  2. Rufen Sie in der Marbles-Probe die Aktion Create a new marble auf, um eine Reihe von Marmor für verschiedene Marmorbesitzer zu erstellen.
  3. Verwenden Sie den REST-Endpunkt Invoke Atomic Transaction, um atomare Transaktionen abzuschließen, die sowohl die Marbles- als auch die Balance Transfer-Proben aufrufen.

Beispiel: Die folgende Transaktion überträgt einen Marmor mit dem Namen marble1 an Tom und sendet 50 Münzen vom Konto a an das Konto b.

{
 "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
}

Wenn in der vorherigen Transaktion beide Transaktionen in der Vorbereitungsphase erfolgreich sind, werden beide Transaktionen im Buch festgeschrieben. Wenn bei einer Transaktion ein Fehler auftritt, wird keine Transaktion in der zweiten Phase festgeschrieben. Stattdessen werden beide Transaktionen zurückgesetzt. Beispiel: Wenn weniger als 50 Münzen auf dem Konto a sind, wird kein Geld aus dem Konto genommen, und kein Marmor wird an Tom übertragen.

Es ist ein bekanntes Problem mit dem Marbles-Beispiel und dem Standardwert des Feldes Marble-Eigentümer aufgetreten. Weitere Informationen finden Sie unter Bekannte Probleme mit Oracle Blockchain Platform.