跨链代码和渠道进行原子更新
您可以使用原子事务处理以原子方式跨渠道和链代码完成多个事务处理。
原子事务是一系列不可分割的数据操作,它们要么都成功,要么都失败。
在将多个链代码部署到单独通道的复杂情况下,原子事务处理非常有用。即使发生网络或系统故障,也可以在运行多个区块链事务处理时使用原子事务处理来保持数据一致性。Oracle Blockchain Platform 通过使用两阶段提交协议来支持原子事务,其中,准备每个数据操作的初始阶段后跟实际提交每个数据操作的阶段。
restproxy/api/v2/atomicTransactions
每个原子事务由两个或多个区块链事务组成。原子事务处理的结果(returnCode 值)为 Success 或 Failure。在原子事务处理中,每个请求的区块链事务处理被拆分为两个不同的操作:一个准备阶段,然后是提交阶段或回退阶段。
- 在准备阶段,每笔交易一如既往地得到认可,但不是最终确定,而是暂存更改并锁定值,以防止其他交易修改暂存的值。
- 如果每个区块链事务处理的准备阶段成功,则使用内置链代码对事务处理进行背书和提交。以前锁定的值将被解锁,原子事务的结果为
Success。 - 如果任何区块链事务处理的准备阶段失败,则通过使用内置链代码再次回退准备阶段成功的所有其他事务处理。暂存的更改将被删除,以前锁定的值将被解锁。原子事务处理的结果为
Failure。
- 原子事务处理仍处于准备阶段,另一个事务处理尝试修改已准备事务处理锁定的密钥。在这种情况下,系统按设计工作。如果您遇到此错误,请重试第二个事务处理。这类似于应用程序如何处理虚拟机读取错误或多版本并发控制 (MVCC) 错误。
- 原子事务处理返回的
GlobalStatus值为HeuristicOutcome。在这种情况下,原子事务处理操作被取消,因为其中一个提交操作失败。这很少发生,可能需要手动解决。试探结果的一个副作用是,某些键可能会被无法提交或回退的事务锁定。在这种情况下,请使用以下 REST API 端点解锁原子事务处理:restproxy/api/v2/atomicTransactions/{globalTransactionId}
方案:使用示例浏览原子事务处理
请考虑以下示例,该示例使用 Oracle Blockchain Platform 附带的两个示例链代码:“余额转移”和“大理石”。余额转账示例表示能够在账户余额之间转账资金的两个交易方。大理石样品可以让你创造大理石,并在业主之间交换它们。您可以使用单个(非原子)交易来购买大理石,方法是在平衡转移链代码中交换资金,并更改大理石链代码中大理石的所有权。但是,如果其中一个事务处理出现错误,则分类账可能处于不一致的状态:资金已转移,但不是大理石,或者大理石已转移但未支付。
在此方案中,您可以将现有链代码与支持原子事务处理的 REST API 端点结合使用。资金的交换和大理石的所有权转让必须都成功,或者两者都失败。如果任一事务处理遇到错误,则不会提交任何事务处理。要浏览此方案,请完成以下步骤:
- 在不同的渠道上安装平衡转移和大理石样品。有关安装示例的详细信息,请参阅了解 Oracle Blockchain Platform Using Samples 。
- 在大理石样品中,调用
Create a new marble操作为各种大理石所有者创建多个大理石。 - 使用
Invoke Atomic TransactionREST 端点完成同时调用大理石和余额传输样本的原子事务处理。
例如,以下事务处理将名为 marble1 的大理石传输到 Tom,并将 50 枚硬币从帐户 a 发送到帐户 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
}
在上一事务处理中,如果两个事务处理都在准备阶段成功,则两个事务处理都会提交到分类账。如果任一事务处理出现错误,则在第二阶段不会提交任何事务处理。而是回退两个事务处理。例如,如果帐户 a 中的硬币少于 50 个,则不会从帐户中取钱,也不会将大理石转移给 Tom。