Transaction
1 MongoDB 트랜잭션이란?
- MongoDB의 트랜잭션은 여러 문서에 대한 읽기와 쓰기 작업을 하나의 논리적 단위로 묶어주는 기능입니다.
- 트랜잭션을 사용하면 여러 작업이 모두 성공하거나 모두 실패하는 것을 보장할 수 있습니다.
- MongoDB 4.0부터 복제 셋에서 다중 문서 트랜잭션을 지원하기 시작했습니다.
- MongoDB 4.2부터는 분산 트랜잭션을 지원하여 샤딩된 클러스터에서도 트랜잭션을 사용할 수 있습니다.
2 트랜잭션의 ACID 특성
- MongoDB의 트랜잭션은 ACID 특성을 보장합니다:
- Atomicity (원자성): 트랜잭션 내의 모든 작업이 성공하거나 모두 실패합니다.
- Consistency (일관성): 트랜잭션 실행 전후로 데이터베이스가 일관된 상태를 유지합니다.
- Isolation (격리성): 동시에 실행되는 트랜잭션들은 서로 영향을 주지 않습니다.
- Durability (지속성): 트랜잭션이 성공적으로 완료되면 그 결과는 영구적으로 저장됩니다.
3 트랜잭션 사용 방법
- Java에서 MongoDB 트랜잭션을 사용하는 방법에는 두 가지가 있습니다:
- Core API (명시적 트랜잭션)
- Callback API (함수 형태의 트랜잭션)
3.1 Core API를 사용한 트랜잭션
Java 예시 - Core API
// MongoDB 클라이언트 설정
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("bankDB");
MongoCollection<Document> accounts = database.getCollection("accounts");
// 세션 시작
ClientSession session = mongoClient.startSession();
TransactionOptions txnOptions = TransactionOptions.builder()
.readPreference(ReadPreference.primary())
.readConcern(ReadConcern.LOCAL)
.writeConcern(WriteConcern.MAJORITY)
.build();
try {
// 트랜잭션 시작
session.startTransaction(txnOptions);
// 계좌에서 출금
accounts.updateOne(session,
Filters.eq("_id", fromAccountId),
Updates.inc("balance", -amount));
// 다른 계좌로 입금
accounts.updateOne(session,
Filters.eq("_id", toAccountId),
Updates.inc("balance", amount));
// 트랜잭션 커밋
session.commitTransaction();
} catch (Exception e) {
// 에러 발생 시 롤백
session.abortTransaction();
throw e;
} finally {
// 세션 종료
session.close();
}
- Core API를 사용할 때는 트랜잭션의 시작, 커밋, 롤백을 직접 제어합니다.
- try-catch 블록을 사용하여 에러 처리를 명시적으로 수행합니다.
3.2 Callback API를 사용한 트랜잭션
Java 예시 - Callback API
// MongoDB 클라이언트 설정
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
MongoDatabase database = mongoClient.getDatabase("bankDB");
MongoCollection<Document> accounts = database.getCollection("accounts");
TransactionOptions txnOptions = TransactionOptions.builder()
.readPreference(ReadPreference.primary())
.readConcern(ReadConcern.LOCAL)
.writeConcern(WriteConcern.MAJORITY)
.build();
// 트랜잭션 실행
ClientSession session = mongoClient.startSession();
try {
session.withTransaction(() -> {
// 계좌에서 출금
accounts.updateOne(session,
Filters.eq("_id", fromAccountId),
Updates.inc("balance", -amount));
// 다른 계좌로 입금
accounts.updateOne(session,
Filters.eq("_id", toAccountId),
Updates.inc("balance", amount));
return "Transaction successful";
}, txnOptions);
} finally {
session.close();
}
- Callback API는 트랜잭션의 커밋과 롤백을 자동으로 처리합니다.
- 코드가 더 간결하고 실수할 가능성이 줄어듭니다.
4 트랜잭션 제한사항
- MongoDB 트랜잭션을 사용할 때 알아야 할 제한사항들이 있습니다:
- 기본 트랜잭션 제한 시간은 60초입니다.
- 단일 트랜잭션의 크기는 16MB로 제한됩니다.
- capped collection에서는 트랜잭션을 사용할 수 없습니다.
- 트랜잭션 내에서는 콜렉션 생성이나 인덱스 생성 같은 관리 작업을 수행할 수 없습니다.