프로덕션 고려 사항
이 페이지의 내용
다음 페이지에는 트랜잭션 실행 에 대한 몇 가지 프로덕션 고려 사항이 나열되어 있습니다. 이는 트랜잭션을 복제본 세트에서 실행 하든 샤딩된 클러스터에서 실행하든 관계없이 적용 . 샤드 클러스터에서 트랜잭션을 실행 경우, 샤딩된 클러스터와 관련된 추가 고려 사항은 프로덕션 고려 사항( 샤딩된 클러스터)을 참조하세요.
가용성
MongoDB는 복제본 세트에서 다중 문서 트랜잭션을 지원합니다.
분산 트랜잭션은 샤딩된 클러스터에서 다중 문서 트랜잭션에 대한 지원을 추가하고 복제본 세트에서 다중 문서 트랜잭션에 대한 기존 지원을 통합합니다.
참고
분산 트랜잭션 및 다중 문서 트랜잭션
이 두 용어가 동의어로 사용됩니다. 분산 트랜잭션은 샤딩된 클러스터 및 복제본 세트의 다중 문서 트랜잭션을 나타냅니다. 다중 문서 트랜잭션(샤딩된 클러스터에서든 또는 복제본 세트에서든 관계 없이)은 분산 트랜잭션이라고 불립니다.
기능 호환성
트랜잭션을 사용하려면 디플로이먼트의 모든 멤버에 대한 FeatureCompatibilityVersion이 최소한 다음과 같아야 합니다.
배포 | 최소 featureCompatibilityVersion |
---|---|
복제본 세트 |
|
샤딩된 클러스터 |
|
멤버의 fCV를 확인하려면 해당 멤버에 연결하고 다음 명령을 실행하세요.
db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
자세한 내용은 setFeatureCompatibilityVersion
도움말 페이지를 참조하세요.
런타임 제한
참고
MongoDB Atlas 에서 최대 트랜잭션 수명을 구성하려면 Atlas 설명서에서 트랜잭션 수명 설정 을 참조하세요.
기본적으로 트랜잭션의 런타임은 1분 미만이어야 합니다. mongod
인스턴스에 대해 transactionLifetimeLimitSeconds
을(를) 사용하여 이 제한을 수정할 수 있습니다. 샤딩된 클러스터의 경우 모든 샤드 복제본 세트 멤버에 대해 매개변수를 수정해야 합니다. 이 한도를 초과하는 거래는 만료된 것으로 간주되며 주기적인 정리 프로세스에 의해 중단됩니다.
샤딩된 클러스터의 경우 commitTransaction
에 maxTimeMS
제한을 지정할 수도 있습니다. 자세한 내용은 샤딩된 클러스터 트랜잭션 시간 제한을 참조하세요.
Oplog 크기 제한
MongoDB는 트랜잭션의 모든 쓰기 작업에 대해 단일 항목을 생성하는 대신, 트랜잭션의 모든 쓰기 작업을 캡슐화하는 데 필요한 만큼의 oplog 항목을 생성합니다. 이렇게 하면 모든 쓰기 작업에 대해 단일 oplog 항목에 의해 부과되는 트랜잭션의 총 16MB 크기 제한이 적용되지 않습니다. 총 크기 제한이 제거되어도 각 oplog 항목은 여전히 BSON 문서 크기 제한인 16MB 내에 있어야 합니다.
와이어드타이거 캐시
스토리지 캐시 압력이 성능에 부정적인 영향을 미치는 것을 방지하려면 다음을 수행합니다.
트랜잭션을 포기하려면 중단하십시오.
트랜잭션의 개별 작업 중에 오류가 발생하면 트랜잭션을 중단하고 다시 시도하세요.
또한 transactionLifetimeLimitSeconds
는 만료된 트랜잭션이 주기적으로 중단되도록 하여 저장소 캐시 압력을 완화합니다.
참고
커밋되지 않은 트랜잭션이 있어 WiredTiger 캐시에 과도한 부하가 생기는 경우 트랜잭션이 중단되고 쓰기 충돌(write conflict) 오류가 반환됩니다.
트랜잭션이 너무 커서 WiredTiger 캐시에 맞지 않으면 트랜잭션이 중단되고 TransactionTooLargeForCache
오류가 반환됩니다.
트랜잭션 및 보안
샤드 구성 제한
writeConcernMajorityJournalDefault
가 false
로 설정된 샤드가 있는 샤딩된 클러스터에서는 트랜잭션을 실행할 수 없습니다. (예: 인메모리 스토리지 엔진을 사용하는 투표 멤버가 있는 샤드)
샤딩된 클러스터 및 중재자
복제본 세트 에 중재자 가 있는 경우 트랜잭션 을 사용하여 샤드 키 를 변경할 수 없습니다. 중재자는 멀티 샤드 트랜잭션에 필요한 데이터 작업에 참여할 수 없습니다.
쓰기 작업이 여러 샤드에 걸쳐 있는 트랜잭션은 트랜잭션 작업 중 어떤 것이든 중재자가 포함된 샤드에서 읽거나 쓰는 경우 오류를 발생시키고 중단됩니다.
잠금 획득
기본적으로 트랜잭션은 트랜잭션 작업에 필요한 잠금을 획득하기 위해 최대 5
밀리초까지 대기합니다. 트랜잭션이 5
밀리초 내에 필요한 잠금을 획득하지 못하면 트랜잭션이 중단됩니다.
트랜잭션은 중단 또는 커밋 시 모든 잠금을 해제합니다.
팁
트랜잭션을 시작하기 직전에 컬렉션을 만들거나 제거할 때 트랜잭션 내에서 컬렉션에 액세스하는 경우 쓰기 고려 "majority"
가 있는 만들기 또는 제거 작업을 실행하여 트랜잭션이 필요한 잠금을 획득할 수 있도록 하세요.
잠금 요청 시간 초과
참고
MongoDB Atlas 클러스터는 setParameter
명령의 사용을 제한합니다. 자세한 내용은 Atlas 설명서 에서 Atlas 에서 지원되지 않는 명령을 참조하세요.
Atlas cluster 매개변수를 수정하려면 Atlas 지원팀에 문의 하세요.
maxTransactionLockRequestTimeoutMillis
매개변수를 사용하여 트랜잭션이 잠금을 획득하기 위해 대기하는 시간을 조정할 수 있습니다. maxTransactionLockRequestTimeoutMillis
늘리면 트랜잭션의 작업이 필요한 잠금을 획득하기 위해 지정된 시간 동안 대기할 수 있습니다. 이를 통해 빠르게 실행되는 메타데이터 작업과 같이 일시적인 동시 잠금 획득 시 트랜잭션이 중단되는 것을 방지할 수 있습니다. 그러나 이렇게 하면 교착 상태에 빠진 트랜잭션 작업의 중단이 지연될 수 있습니다.
maxTransactionLockRequestTimeoutMillis
을(를) -1
으로 설정하여 작업별 시간 제한을 사용할 수도 있습니다.
보류 중인 DDL 작업 및 트랜잭션
다중 문서 트랜잭션이 진행 중인 경우 동일한 데이터베이스 또는 컬렉션에 영향을 주는 새 DDL 작업이 트랜잭션 뒤에서 대기합니다. 이러한 보류 중인 DDL 작업이 있는 동안 보류 중인 DDL 작업과 동일한 데이터베이스 또는 컬렉션에 액세스하는 새 트랜잭션은 필요한 잠금을 얻을 수 없으며 maxTransactionLockRequestTimeoutMillis
대기 후 중단됩니다. 또한 동일한 데이터베이스 또는 컬렉션에 액세스하는 새로운 비트랜잭션 작업은 maxTimeMS
제한에 도달할 때까지 차단됩니다.
다음 시나리오를 고려하세요.
- 컬렉션 잠금이 필요한 DDL 작업
진행 중인 트랜잭션이
hr
데이터베이스의employees
컬렉션에 대해 다양한 CRUD 작업을 수행하는 동안 관리자가employees
컬렉션 에 대해db.collection.createIndex()
DDL 작업을 실행합니다.createIndex()
컬렉션에 대한 배타적 컬렉션 잠금이 필요합니다.진행 중인 트랜잭션이 완료될 때까지는
createIndex()
작업을 기다려야 잠금을 획득할 수 있습니다.employees
collection에 영향을 미치고createIndex()
가 보류 중인 동안 시작되는 신규 트랜잭션의 경우,createIndex()
가 완료될 때까지 기다려야 합니다.보류 중인
createIndex()
DDL 작업은hr
데이터베이스의 다른 컬렉션에 대한 트랜잭션에 영향을 주지 않습니다. 예를 들어,hr
데이터베이스의contractors
컬렉션에 대한 새 트랜잭션은 정상적으로 시작되고 완료될 수 있습니다.- 데이터베이스 잠금이 필요한 DDL 작업
진행 중인 트랜잭션 이
hr
데이터베이스 의employees
컬렉션 에 대해 다양한 CRUD 작업을 수행하는 동안 관리자가renameCollection
DDL 작업을 실행하여vendors.contractors
컬렉션 의 이름을hr.contractors
로 변경합니다.renameCollection
은(는) 대상 데이터베이스 (hr
)가 소스 데이터베이스 (vendors
)와 다른 경우 데이터베이스 락 이 필요합니다.진행 중인 트랜잭션 이 완료될 때까지
renameCollection
작업은 락 을 획득하기 위해 기다려야 합니다.hr
데이터베이스 또는 해당 컬렉션에 영향을 미치고renameCollection
가 보류 중인 동안 시작되는 모든 새 트랜잭션 은renameCollection
이 완료될 때까지 기다려야 합니다.
어느 시나리오에서든 DDL 작업이 maxTransactionLockRequestTimeoutMillis
이상 보류 상태로 남아 있으면 해당 작업 뒤에 대기 중인 트랜잭션이 중단됩니다. 즉, maxTransactionLockRequestTimeoutMillis
값은 최소한 진행 중인 트랜잭션과 보류 중인 DDL 작업을 완료하는 데 필요한 시간을 포함해야 합니다.
진행 중인 트랜잭션 및 쓰기 충돌
트랜잭션이 진행 중이고 트랜잭션 외부의 쓰기가 나중에 트랜잭션의 작업이 수정하려고 하는 문서를 수정하는 경우, 쓰기 충돌로 인해 트랜잭션이 중단됩니다.
트랜잭션이 진행 중이고 문서 수정을 잠긴 경우 트랜잭션 외부에서 쓰기가 동일한 문서를 수정하려고 하면 트랜잭션이 종료될 때까지 쓰기가 대기합니다.
진행 중인 트랜잭션 및 오래된 읽기
트랜잭션 내부의 읽기 작업은 오래된 데이터를 반환할 수 있으며 이를 부실 읽기라고 합니다. 트랜잭션 내부의 읽기 작업은 커밋된 다른 트랜잭션이나 트랜잭션이 아닌 쓰기에서 수행되는 쓰기를 볼 수 없습니다. 예를 들어 다음 순서를 생각해 보세요.
트랜잭션이 진행 중입니다.
트랜잭션 외부에서 쓰면 문서가 삭제됩니다.
트랜잭션 내부의 읽기 작업은 쓰기 작업 이전의 스냅샷을 사용하므로 현재 삭제된 문서를 읽을 수 있습니다.
단일 문서에 대한 트랜잭션 내부의 오래된 읽기를 방지하려면 db.collection.findOneAndUpdate()
메서드를 사용할 수 있습니다. 다음 mongosh
예시에서는 db.collection.findOneAndUpdate()
(을)를 사용하여 쓰기 잠금을 설정하고 읽기를 최신 상태로 유지하는 방법을 보여 줍니다.
컬렉션 에 employees
문서 삽입
db.getSiblingDB("hr").employees.insertOne( { _id: 1, status: "Active" } )
트랜잭션 db.collection.findOneAndUpdate()
내에서사용
employeeDoc = employeesCollection.findOneAndUpdate( { _id: 1, status: "Active" }, { $set: { lockId: ObjectId() } }, { returnNewDocument: true } )
트랜잭션 내에서 findOneAndUpdate
작업은 새 lockId
필드를 설정합니다. 문서를 수정하는 한 lockId
필드를 어떤 값으로든 설정할 수 있습니다. 문서를 업데이트하면 트랜잭션이 잠금을 획득합니다.
트랜잭션 외부의 작업이 트랜잭션을 커밋하기 전에 문서를 수정하려고 시도하면 MongoDB는 외부 작업에 쓰기 충돌 오류를 반환합니다.
진행 중인 트랜잭션 및 청크 마이그레이션
청크 마이그레이션은 특정 단계에서 배타 (Exclusive) 컬렉션 락을 획득합니다.
진행 중인 트랜잭션에 컬렉션에 대한 락이 있고 해당 컬렉션을 포함하는 청크 마이그레이션이 시작되면 이러한 마이그레이션 단계는 트랜잭션이 컬렉션에 락을 해제할 때까지 기다려야 하므로 청크 마이그레이션 성능에 영향을 미칩니다.
청크 마이그레이션이 트랜잭션과 중첩되는 경우 (예를 들어 청크 마이그레이션이 이미 진행 중인 동안 트랜잭션이 시작되고, 컬렉션에 대한 락을 트랜잭션이 실행하기 전에 마이그레이션이 완료되는 경우), 트랜잭션은 커밋 시 오류가 발생하고 중단됩니다.
두 작업이 어떻게 교차하는지에 따라 샘플 오류에는 다음과 같습니다. (오류 메시지는 축약됨).
an error from cluster data placement change ... migration commit in progress for <namespace>
Cannot find shardId the chunk belonged to at cluster time ...
커밋 중 외부 읽기
트랜잭션을 커밋하는 동안 외부 읽기 작업은 트랜잭션에 의해 수정될 동일한 문서를 읽으려고 할 수 있습니다. 트랜잭션이 여러 샤드에 쓰는 경우 샤드 전체에 걸쳐 커밋을 시도하는 동안 다음이 수행됩니다.
"snapshot"
또는"linearizable"
읽기 우려 (read concern)를 사용하는 외부 읽기는 트랜잭션의 모든 쓰기가 표시될 때까지 기다립니다.인과적으로 일관적인 세션의 일부인 외부 읽기 (AfterClusterTime 포함하는 세션)는 트랜잭션의 모든 쓰기가 표시될 때까지 대기합니다.
다른 읽기 고려 (read concern)를 사용하는 외부 읽기는 트랜잭션의 모든 쓰기가 표시될 때까지 기다리지 않고 대신 문서의 트랜잭션 이전 버전을 읽습니다.