Session.abortTransaction()
정의
Session.abortTransaction()
다중 문서 트랜잭션 을 종료하고 트랜잭션 내의 작업으로 인해 변경된 모든 데이터를 롤백합니다. 즉, 트랜잭션 작업으로 인한 변경 사항을 저장하지 않고 트랜잭션 이 종료됩니다.
중요
Mongo쉬 방법
이 페이지에서는
mongosh
메서드를 설명합니다. 이는 데이터베이스 명령 또는 Node.js와 같은 언어별 드라이버에 대한 설명서가 아닙니다.데이터베이스 명령에 대해서는
abortTransaction
명령을 참조하십시오.MongoDB API 드라이버의 경우 언어별 MongoDB 드라이버 설명서를 참조하세요.
버전 4.2에서 변경 : MongoDB 4.2부터 샤딩된 클러스터와 복제본 세트 모두에서 다중 문서 트랜잭션을 사용할 수 있습니다.
행동
원자성
트랜잭션이 중단되면 트랜잭션 쓰기로 인한 모든 데이터 변경 사항이 표시되지 않고 삭제되며 트랜잭션이 종료됩니다.
보안
감사와 함께 실행하는 경우 중단된 트랜잭션의 작업은 계속 감사됩니다.
재시도 가능
중단 작업에서 오류가 발생하면 MongoDB 드라이버는 retryWrites
가 true
로 설정되었는지 여부에 관계없이 중단 작업을 한 번 재시도합니다. 자세한 내용은 트랜잭션 오류 처리를 참조하세요.
예시
hr
데이터베이스의 직원 기록이 변경될 때 reporting
데이터베이스의 events
컬렉션이 hr
변경 사항과 동기화되도록 하거나 혹은 그 반대로 수행하려는 시나리오를 생각해 보겠습니다. 즉, 이러한 쓰기가 단일 트랜잭션으로 수행되어 두 작업이 모두 성공하거나 실패하도록 해야 합니다.
hr
데이터베이스의 employees
컬렉션에는 다음 문서가 포함되어 있습니다.
{ "_id" : ObjectId("5af0776263426f87dd69319a"), "employee" : 3, "name" : { "title" : "Mr.", "name" : "Iba Ochs" }, "status" : "Active", "department" : "ABC" } { "_id" : ObjectId("5af0776263426f87dd693198"), "employee" : 1, "name" : { "title" : "Miss", "name" : "Ann Thrope" }, "status" : "Active", "department" : "ABC" } { "_id" : ObjectId("5af0776263426f87dd693199"), "employee" : 2, "name" : { "title" : "Mrs.", "name" : "Eppie Delta" }, "status" : "Active", "department" : "XYZ" }
employees
컬렉션에는 employee
필드에 고유 인덱스가 있습니다.
db.employees.createIndex( { employee: 1 }, { unique: true } )
reporting
데이터베이스의 events
컬렉션에는 다음 문서가 포함되어 있습니다.
{ "_id" : ObjectId("5af07daa051d92f02462644a"), "employee" : 1, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } } { "_id" : ObjectId("5af07daa051d92f02462644b"), "employee" : 2, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "XYZ", "old" : null } } { "_id" : ObjectId("5af07daa051d92f02462644c"), "employee" : 3, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } }
다음 예에서는 트랜잭션을 열고 events
컬렉션에 레코드를 추가하고 employees
컬렉션에 문서를 추가하려고 시도합니다. 작업 중 하나 또는 트랜잭션 커밋 중 오류가 발생하면 세션이 트랜잭션을 중단합니다.
// Runs the txnFunc and retries if TransientTransactionError encountered function runTransactionWithRetry(txnFunc, session) { while (true) { try { txnFunc(session); // performs transaction break; } catch (error) { // If transient error, retry the whole transaction if (error?.errorLabels?.includes("TransientTransactionError")) { print("TransientTransactionError, retrying transaction ..."); continue; } else { throw error; } } } } // Retries commit if UnknownTransactionCommitResult encountered function commitWithRetry(session) { while (true) { try { session.commitTransaction(); // Uses write concern set at transaction start. print("Transaction committed."); break; } catch (error) { // Can retry commit if (error?.errorLabels?.includes("UnknownTransactionCommitResult") ) { print("UnknownTransactionCommitResult, retrying commit operation ..."); continue; } else { print("Error during commit ..."); throw error; } } } } // Performs inserts and count in a transaction function updateEmployeeInfo(session) { employeesCollection = session.getDatabase("hr").employees; eventsCollection = session.getDatabase("reporting").events; // Start a transaction for the session that uses: // - read concern "snapshot" // - write concern "majority" session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } ); try{ eventsCollection.insertOne( { employee: 3, status: { new: "Active", old: null }, department: { new: "XYZ", old: null } } ); // Count number of events for employee 3 var countDoc = eventsCollection.aggregate( [ { $match: { employee: 3 } }, { $count: "eventCounts" } ] ).next(); print( "events count (in active transaction): " + countDoc.eventCounts ); // The following operations should fail as an employee ``3`` already exist in employees collection employeesCollection.insertOne( { employee: 3, name: { title: "Miss", name: "Terri Bachs" }, status: "Active", department: "XYZ" } ); } catch (error) { print("Caught exception during transaction, aborting."); session.abortTransaction(); throw error; } commitWithRetry(session); } // End of updateEmployeeInfo function // Start a session. session = db.getMongo().startSession( { readPreference: { mode: "primary" } } ); try{ runTransactionWithRetry(updateEmployeeInfo, session); } catch (error) { // Do something with error } finally { session.endSession(); }