체인코드 및 채널 전체에서 원자 갱신
원자 트랜잭션을 사용하여 원자 방식으로 채널과 체인코드 간에 여러 트랜잭션을 완료할 수 있습니다.
원자 트랜잭션은 모두 성공하거나 성공하지 못한 일련의 분할할 수 없는 데이터 작업입니다.
원자 트랜잭션은 여러 체인 코드가 별도의 채널에 배치되는 복잡한 상황에서 유용할 수 있습니다. 네트워크 또는 시스템 장애가 발생하더라도 원자 트랜잭션을 사용하여 여러 블록체인 트랜잭션을 실행하는 동안 데이터 일관성을 유지할 수 있습니다. Oracle Blockchain Platform은 2단계 커밋 프로토콜을 사용하여 원자 트랜잭션을 지원합니다. 여기서 각 데이터 작업이 준비되는 초기 단계 다음에 각 데이터 작업이 실제로 커밋되는 단계가 옵니다.
restproxy/api/v2/atomicTransactions
각 원자 거래는 둘 이상의 블록체인 거래로 구성됩니다. 원자 트랜잭션의 결과(returnCode 값)는 Success 또는 Failure입니다. 원자 트랜잭션에서 요청된 각 블록체인 트랜잭션은 준비 단계와 커밋 단계 또는 롤백 단계라는 두 개의 개별 작업으로 분할됩니다.
- 준비 단계에서는 각 트랜잭션이 평소처럼 배서되지만, 완료되는 대신 변경 사항이 스테이지되고 다른 트랜잭션이 스테이지된 값을 수정하지 못하도록 값이 잠깁니다.
- 각 블록체인 트랜잭션에 대한 준비 단계가 성공하면 트랜잭션은 내장된 체인코드를 사용하여 승인되고 커밋됩니다. 이전에 잠긴 값은 잠금 해제되고 기본 트랜잭션 결과는
Success입니다. - 블록체인 트랜잭션에 대한 준비 단계가 실패하면 준비 단계가 성공한 다른 모든 트랜잭션은 다시 내장된 체인코드를 사용하여 롤백됩니다. 스테이지된 변경 사항이 제거되고 이전에 잠긴 값이 잠금 해제됩니다. 원자 트랜잭션의 결과는
Failure입니다.
- 원자 트랜잭션은 여전히 준비 단계에 있으며 다른 트랜잭션은 준비된 트랜잭션에 의해 잠긴 키를 수정하려고 시도합니다. 이 경우 시스템은 설계된 대로 작동합니다. 이 오류가 발생하면 두번째 트랜잭션을 재시도하십시오. 이는 응용 프로그램이 팬텀 읽기 오류 또는 MVCC(다중 버전 동시성 제어) 오류를 처리하는 방법과 유사합니다.
- 기본 트랜잭션에서 반환된
GlobalStatus값은HeuristicOutcome입니다. 이 경우 커밋 작업 중 하나가 실패하여 기본 트랜잭션 작업이 취소되었습니다. 드문 경우이지만 수동으로 해결해야 할 수도 있습니다. 휴리스틱 결과의 한 가지 부작용은 커밋되거나 롤백되지 않은 트랜잭션에 의해 일부 키가 잠긴 상태로 유지될 수 있다는 것입니다. 이 경우 다음 REST API 끝점을 사용하여 기본 트랜잭션의 잠금을 해제합니다.restproxy/api/v2/atomicTransactions/{globalTransactionId}
시나리오: 샘플을 사용하여 기본 트랜잭션 탐색
Oracle Blockchain Platform에 포함된 두 개의 샘플 체인코드인 잔액 이전 및 마블을 사용하는 다음 예를 고려해 보십시오. 잔액 이체 샘플은 계정 잔액 간에 자금을 이체할 수 있는 두 당사자를 나타냅니다. Marbles 샘플을 사용하면 대리석을 만들고 소유자 간에 교환할 수 있습니다. 잔액 이체 체인 코드에서 자금을 교환하고 Marbles 체인 코드에서 대리석 소유권을 변경하여 개별(비원자) 거래를 사용하여 대리석을 구매할 수 있습니다. 그러나 해당 거래 중 하나에서 오류가 발생하면 원장이 불일치 상태로 남을 수 있습니다. 자금이 이전되었지만 대리석이 아니거나 대리석이 이전되었지만 지급되지 않았습니다.
이 시나리오에서는 기본 트랜잭션을 지원하는 REST API 엔드포인트와 함께 기존 체인코드를 사용할 수 있습니다. 자금 교환 및 대리석 소유권 이전은 모두 성공하거나 둘 다 실패해야 합니다. 두 트랜잭션 중 하나에서 오류가 발생하면 어떤 트랜잭션도 커밋되지 않습니다. 이 시나리오를 살펴보려면 다음 단계를 완료하십시오.
- 다른 채널에 밸런스 전송 및 마블 샘플을 설치합니다. 샘플 설치에 대한 자세한 내용은 샘플을 사용하여 Oracle Blockchain Platform 살펴보기를 참조하십시오.
- Marbles 샘플에서
Create a new marble작업을 호출하여 다양한 대리석 소유자를 위한 여러 대리석을 만듭니다. Invoke Atomic TransactionREST 엔드포인트를 사용하여 Marbles 및 잔액 이전 샘플을 모두 호출하는 기본 트랜잭션을 완료합니다.
예를 들어, 다음 트랜잭션은 이름이 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
}
이전 트랜잭션에서 두 트랜잭션이 모두 준비 단계에서 성공하면 두 트랜잭션이 모두 원장에 커밋됩니다. 두 트랜잭션 중 하나에 오류가 있으면 두번째 단계에서 트랜잭션이 커밋되지 않습니다. 대신 두 트랜잭션이 모두 롤백됩니다. 예를 들어, 계정 a에 동전이 50개 미만인 경우 계정에서 돈을 받지 않고 Tom에게 대리석이 전송되지 않습니다.
Marbles 샘플 및 Marble Owner 필드의 기본값과 관련하여 알려진 문제가 있습니다. 자세한 내용은 Oracle Blockchain Platform에 대한 알려진 문제를 참조하십시오.