문서 메뉴

문서 홈애플리케이션 개발MongoDB 매뉴얼

Session.startTransaction()

이 페이지의 내용

  • 정의
  • 행동
  • 예제
Session.startTransaction(<options>)

세션과 연결된 다중 문서 트랜잭션을 시작합니다. 주어진 시간에 세션에 대해 열려 있는 트랜잭션은 최대 하나만 있을 수 있습니다.

버전 4.2에서 변경 : MongoDB 4.2부터 샤딩된 클러스터와 복제본 세트 모두에서 다중 문서 트랜잭션을 사용할 수 있습니다.

중요

트랜잭션 내에서는 기존 collection에 대한 읽기 및 쓰기(CRUD) 작업만 지정할 수 있습니다. 예를 들어 다중 문서 트랜잭션에는 새 컬렉션을 생성하는 삽입 작업이 포함될 수 없습니다.

Session.startTransaction() 메서드는 다음 옵션을 사용하여 문서를 가져올 수 있습니다.

{ readConcern: { level: <level>}, writeConcern: { w: <value>, j: <boolean>, wtimeout: <number> } }
옵션
설명
readConcern

선택 사항입니다. 트랜잭션의 모든 연산에 대한 읽기 고려를 지정하는 문서로, 연산별 읽기 고려를 재정의합니다.

다음 읽기 고려 수준 중 하나를 지정할 수 있습니다.

"local""majority" 읽기 고려에 대해 MongoDB는 때로 더 강력한 읽기 고려로 대체할 수 있습니다.

writeConcern

선택 사항. 트랜잭션에서의 쓰기 고려를 지정하는 문서입니다. 이 쓰기 고려는 트랜잭션 커밋과 중단 작업에 적용됩니다.

트랜잭션 내의 작업은 "w: 1"을 사용하여 작업별 쓰기 고려를 재정의합니다.

"w: 1" 쓰기 고려를 사용하여 커밋하는 경우 페일오버 프로세스 중에 트랜잭션이 롤백될 수 있습니다.

MongoDB 드라이버의 경우, 트랜잭션은 클라이언트 수준 쓰기 고려를 기본값으로 사용합니다.

참고

액세스 제어를 사용하여 실행하는 경우 트랜잭션의 작업에 대한 권한이 있어야 합니다.

다중 문서 트랜잭션의 경우:

  • 트랜잭션에서 컬렉션과 인덱스를 생성할 수 있습니다. 자세한 내용은 트랜잭션에서 컬렉션 및 인덱스 생성하기를 참조하세요

  • 트랜잭션에 사용되는 컬렉션은 서로 다른 데이터베이스에 있을 수 있습니다.

    참고

    샤드 간 쓰기 트랜잭션에서는 새 컬렉션을 생성할 수 없습니다. 예를 들어, 하나의 샤드에서 기존 컬렉션에 쓰고 다른 샤드에서 암시적으로 새 컬렉션을 생성하는 경우, MongoDB는 동일한 트랜잭션에서 두 작업을 모두 수행할 수 없습니다.

  • 제한된 컬렉션에는 쓸 (write) 수 없습니다.

  • 고정 사이즈 컬렉션에서 읽을 때는 읽기 고려 "snapshot"을 사용할 수 없습니다. (MongoDB 5.0부터 도입됨)

  • config, admin 또는 local 데이터베이스의 컬렉션을 읽고 쓸 수 없습니다.

  • system.* 컬렉션에 쓸 수 없습니다.

  • explain 또는 이와 유사한 명령을 사용하여 지원되는 작업의 쿼리 계획을 반환할 수 없습니다.

  • 트랜잭션 외부에서 생성된 커서의 경우 트랜잭션 내부에서 getMore을(를) 호출할 수 없습니다.

  • 트랜잭션에서 생성된 커서의 경우 트랜잭션 외부에서 getMore를 호출할 수 없습니다.

메서드
명령
참고

다음 쿼리 연산자 표현식은 제외됩니다.

이 메서드는 쿼리에 $match 애그리게이션 단계를 사용하고 $sum 표현식이 있는 $group 애그리게이션 단계를 사용하여 계산을 수행합니다.

비샤드형 컬렉션에서 사용할 수 있습니다.

샤드 컬렉션의 경우 $group 단계로 aggregation pipeline을 사용합니다. 고유 작업을 참조하세요.

존재하지 않는 collection에서 upsert: true )로 업데이트 또는 바꾸기 작업을 실행하면 collection이 암시적으로 생성됩니다.

MongoDB 4.2 이하 버전에서 upsert: true인 경우 기존 컬렉션에서 작업을 실행해야 합니다.

다음도 참조하세요.

존재하지 않는 컬렉션에서 실행하면 컬렉션이 암시적으로 생성됩니다.

MongoDB 4.2 이하 버전에서는 기존 컬렉션에서 작업을 실행해야 합니다.

다음도 참조하세요.

존재하지 않는 컬렉션에서 실행하면 컬렉션이 암시적으로 생성됩니다.

MongoDB 4.2 이하 버전에서는 기존 컬렉션에서 작업을 실행해야 합니다.

다음도 참조하세요.

존재하지 않는 컬렉션에서 실행하면 컬렉션이 암시적으로 생성됩니다.

MongoDB 4.2 이하 버전에서는 기존 컬렉션에서 작업을 실행해야 합니다.

다음도 참조하세요.

컬렉션이나 인덱스 생성 또는 삭제 등 데이터베이스 카탈로그에 영향을 주는 작업은 다중 문서 트랜잭션에서 허용되지 않습니다. 예를 들어, 다중 문서 트랜잭션에는 새 컬렉션을 생성하는 삽입 작업이 포함될 수 없습니다. 제한된 작업을 참조하세요.

2} buildInfo,helloconnectionStatus , 과 같은 정보 명령(및 그 도우미 메서드) (및 해당 헬퍼 메서드)와 같은 정보 명령은 트랜잭션에서 허용되지만, 트랜잭션의 첫 번째 연산이 될 수는 없습니다.

트랜잭션 은 읽기 설정 (read preference) primary 을 지원합니다.

트랜잭션이 열려 있는 동안에는 트랜잭션 연산으로 인한 데이터 변경 사항이 트랜잭션 외부에 표시되지 않습니다.

  • 트랜잭션이 커밋되면 트랜잭션에서 이루어진 모든 데이터 변경 사항이 저장되고 트랜잭션 외부에서 볼 수 있습니다. 즉, 트랜잭션은 다른 트랜잭션을 롤백하는 동안 다른 변경 사항을 커밋하지 않습니다.

    트랜잭션이 커밋될 때까지 트랜잭션에서 변경된 데이터는 트랜잭션 외부에 표시되지 않습니다.

    그러나 트랜잭션이 여러 샤드에 쓰기를 수행하는 경우, 모든 외부 읽기 작업이 커밋된 트랜잭션의 결과가 샤드 전체에 표시될 때까지 기다릴 필요는 없습니다. 예를 들어, 트랜잭션이 커밋되고 쓰기 1이 샤드 A에 표시되지만 쓰기 2가 샤드 B에 아직 표시되지 않는 경우, 읽기 고려 "local"의 외부 읽기는 쓰기 2를 보지 않고 쓰기 1의 결과를 읽을 수 있습니다.

  • 트랜잭션이 중단되면 트랜잭션 쓰기로 인한 모든 데이터 변경 사항이 표시되지 않고 삭제되며 트랜잭션이 종료됩니다.

hr 데이터베이스의 직원 기록이 변경될 때 reporting 데이터베이스의 events collection이 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" }

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

다음 예에서는 트랜잭션을 열고 employees 상태에서 직원의 상태를 Inactive로 업데이트하고 events 컬렉션에 해당 문서를 삽입하고 두 작업을 단일 트랜잭션으로 커밋합니다.

// 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;
}
}
}
}
// Updates two collections in a transactions
function updateEmployeeInfo(session) {
employeesCollection = session.getDatabase("hr").employees;
eventsCollection = session.getDatabase("reporting").events;
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
try{
employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } );
eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
} catch (error) {
print("Caught exception during transaction, aborting.");
session.abortTransaction();
throw error;
}
commitWithRetry(session);
}
// Start a session.
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
try{
runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
// Do something with error
} finally {
session.endSession();
}
← Session.commitTransaction()

이 페이지의 내용