튼튼발자 개발 성장기🏋️

[MongoDB] 트랜잭션 본문

기타/MongoDB

[MongoDB] 트랜잭션

시뻘건 튼튼발자 2025. 3. 23. 11:14
반응형

트랜잭션(Transaction)이란?

트랜잭션은 읽기나 쓰기 작업이 가능한 데이터베이스 작업을 하나 이상 포함하는 데이터베이스의 논리적 처리 단위이며 각 그룹과 트랜잭션은 여러 도큐먼트에 대한 읽기, 쓰기와 같은 작업을 하나 이상 포함할 수 있다. MongoDB의 경우에는 여러 작업, 컬렉션, 데이터베이스, 도큐먼트 및 샤드에서 ACID 호환 트랜잭션을 지원한다.

트랜잭션의 주요 특징

  1. 원자성 (Atomicity): 트랜잭션 내 모든 작업이 성공해야만 최종적으로 커밋된다.
  2. 일관성 (Consistency): 데이터가 트랜잭션 시작 전후로 일관성을 유지한다.
  3. 고립성 (Isolation): 트랜잭션이 완료되기 전까지 다른 작업에서 변경된 데이터를 볼 수 없다.
  4. 영속성 (Durability): 트랜잭션이 완료되면 데이터가 영구적으로 저장된다.

트랜잭션 API

MongoDB에서는 트랜잭션을 사용하기 위한 두 가지 API를 제공하고 있는데 하나는 Core api이고 나머지 하나는 Callback api이다. 참고로 callback api를 사용하는 것을 권장하고있다. 왜냐하면 core api는 대부분의 오류에 재시도 로직을 제공하지 않으며 개발자가 작업에 대한 로직, 트랜잭션 커밋 함수, 필요한 재시도 및 오류 핸들 로직을 모두 작성해야하기 때문이다.

트랜잭션을 사용하려면 클라이언트 세션을 생성하고 트랜잭션을 시작해야 하며 트랜잭션의 작업이 세션에 전달해야한다. 아래 예제를 보자.

String uri = "mongodb://my0.mongodb.com:27017";
final MongoClient client = MongoClients.create(uri);

// collection 생성
client.getDatabase("mydb1")
	.getCollection("foo")
	.withWriteConcern(WriteConcern.MAJORITY)
	.insertOne(new Document("abc", 0));
client.getDatabase("mydb2")
	.getCollection("bar")
	.withWriteConcern(WriteConcern.MAJORITY)
	.insertOne(new Document("xyz", 0));
    
// 클라이언트 세션
final ClientSession clientSession = client.startSession();

// 트랜잭션 옵션 설정
TransactionOptions txnOptions = TransactionOptions.builder()
	.writeConcern(WriteConcern.MAJORITY)
	.build();

// 트랜잭션 작업 지정
TransactionBody txnBody = new TransactionBody<String>() {
	public String execute() {
		MongoCollection<Document> coll1 = client.getDatabase("mydb1")
			.getCollection("foo");
		MongoCollection<Document> coll2 = client.getDatabase("mydb2")
			.getCollection("bar");
        
		// 작업을 세션에 전달
		coll1.insertOne(clientSession, new Document("abc", 1));
		coll2.insertOne(clientSession, new Document("xyz", 999));
		return "Inserted into collections in different databases";
	}
};

// 트랜잭션 시작
try {
    // 콜백이 실행되고 커밋
    clientSession.withTransaction(txnBody, txnOptions);
} catch (RuntimeException e) {
    // 예외 처리
} finally {
    clientSession.close();
}

트랜잭션의 성능 최적화

MongoDB에서 트랜잭션을 사용할 때 고려해야하는 중요한 설정 두 가지가 있다.

첫 번째는 트랜잭션의 시간 제한이다. 즉 특정 트랜잭션이 실행될 수 있는 시간, 트랜잭션이 락을 획득하려고 대기하는 시간, 모든 트랜잭션이 실행될 최대 길이를 제어하는 것과 관련이 있다.

두 번째는 oplog 항목과 개별 항목에 대한 크기 제한과 관련이 있다.

더보기

[oplog 용어 설명]

 

oplog: MongoDB 데이터베이스에 대한 논리적 쓰기의 순서가 지정된 기록을 저장하는 고정 사이즈 컬렉션이다. oplog는 MongoDB에서 복제를 가능하게 하는 기본 메커니즘이다.

 

oplog 버퍼 컬렉션: 리샤딩 작업 중에 생성되어 기증자 샤드의 oplog항목을 저장하는 임시 컬렉션이다. oplog 버퍼 컬렉션은 기증자 샤드에서 oplog 항목이 삭제될 때 수신자 샤드가 해당 항목에 액세스할 수 있도록 보장한다. 리샤딩이 완료되면 oplog 버퍼 컬렉션이 제거된다.

 

oplog hole: oplog 쓰기가 순서대로 이루어지지 않기 때문에 oplog에 일시적인 공백이 발생한다. 복제본 세트 프라이머리는 배치 작업으로 oplog 항목을 병렬로 적용한다. 그 결과, 배치에서 아직 작성되지 않은 항목으로 인해 oplog에 일시적인 공백이 발생할 수 있다.

 

oplog window: oplog 항목에는 타임스탬프가 기록되어 있다. oplog window는 oplog에서 가장 최근의 타임스탬프와 가장 오래된 타임스탬프 사이의 시간 차이다. 세컨더리 노드가 프라이머리 노드와의 연결이 끊어지는 경우 oplog window 내에서 연결이 복원된 경우에만 복제를 사용하여 다시 동기화할 수 있다.

 

optime: 복제 oplog 위치에 대한 참조다. optime 값은 다음을 포함하는 문서다.

  • ts: 작업의 타임스탬프.
  • t: 작업이 원래 프라이머리에서 생성된 term

트랜잭션 시간 제한

transactionLifetimeLimitSeconds

트랜잭션의 최대 실행 시간은 기본 60초이다. 이는 `transactionLifetimeLimitSeconds `매개변수를 통해 설정할 수 있다. 샤드 클러스터의 경우 모든 샤드 복제 셋 멤버에 매개변수를 설정해야한다. 이 시간이 경과되면 트랜잭션이 만료됐다고 간주하며 주기적인 정리 프로세스를 통해 중단된다. 정리 프로세스는 (`transactionLifetimeLimitSeconds` / 2)초마다 또는 60초에 한 번 이상 실행된다. 만약 트랜잭션에 명시적으로 시간제한을 설정하려면 `commitTransaction`에 `maxTimeMS`를 지정하면 된다. 다만, ` maxTimeMS`가 적용되지 않으면 `transactionLifetimeLimitSeconds`가 적용된다. 참고로 이 설정의 최소 값은 1이다.

 

maxTransactionLockRequestTimeoutMillis

트랜잭션의 작업에 필요한 락을 획득하기 위해 트랜잭션이 대기하는 최대 시간은 최대 5ms이다. 이 값은 `maxTransactionLockRequestTimeoutMillis`에 의해 결정된다.트랜잭션이 이 시간동안 잠금을 획득하지 못하면 트랜잭션이 중단다. 만약 이 값이 0이면 트랜잭션이 필요한 잠금을 즉시 획득할 수 없으면 트랜잭션이 중단된다.

 

oplog 크기 제한

MongoDB는 트랜잭션의 쓰기 작업에 필요한 만큼 oplog 항목을 생성한다. 그러나 각 oplog 항목은 도큐먼트 크기 제한인 16MB 이하여야한다.

트랜잭션은 일관성을 보장하기 위해 MongoDB에서 유용한 기능을 제공하지만 풍부한 도큐먼트 모델과 함께 사용되어야한다. 유연한 모델과 스키마 설계 패턴과 같은 모범 사례를 사용하면  대부분의 상황에서 트랜잭션을 사용하지 않아도 된다. 따라서 트랜잭션은 애플리케이션에서 드물게 사용하는 것이 좋은 강력한 기능이다.

유연한 모델과 스키마 설계 패턴에 대한 내용은 다음에 알아보도록 하자.

반응형

'기타 > MongoDB' 카테고리의 다른 글

[MongoDB] 영속성  (0) 2025.03.23
[MongoDB] 특수 인덱스  (0) 2025.03.17
[MongoDB] 인덱싱 #2  (0) 2025.03.16
[MongoDB] 인덱싱 #1  (0) 2025.03.15
[MongoDB] 도큐먼트 생성, 갱신, 삭제  (0) 2025.03.06