1. 트랜잭션 소개
- 트랜잭션은 읽기나 쓰기 작업이 가능한 데이터베이스 작업을 하나 이상 포함하는 데이터베이스의 논리적 단위
- 트랜잭션의 중요한 특징은 작업이 성공하든 실패하든 부분적으로는 완료되지 않는다는 점
- 몽고DB에서 트랜잭션을 사용하려면 버전이 4.2 이상이어야 하며 몽고DB 드라이버를 몽고DB 4.2 이상에 맞게 갱신해야 함
1.1 ACID의 정의
- 트랜잭션이 `진정한` 트랜잭션이 되려면 ACID라는 속성을 충족해야 함
- ACID는 원자성 (Atomicity), 일관성 (Consistency), 고립성 (Isolation), 그리고 영속성 (Durability)의 약어
- ACID 트랜잭션은 오류가 발생할 때도 데이터와 데이터베이스의 상태의 유효성을 보장
- 원자성 (Atomicity)은 트랜잭션 내 모든 작업이 적용되거나 아무 작업도 적용되지 않도록 보장하며 트랜잭션은 부분적으로 적용될 수 없음
- 즉, 커밋되거나 중단됨
- 일관성 (Consistency)은 트랜잭션이 성공하면 데이터베이스가 하나의 일관성 있는 상태에서 다음 일관성 있는 상태로 이동하도록 보장
- 고립성 (Isolation)은 여러 트랜잭션이 데이터베이스에서 동시에 실행되도록 허용하는 속성
- 트랜잭션이 다른 트랜잭션의 부분 결과를 보지 않도록 보장
- 여러 병령 트랜잭션이 각 트랜잭션을 순차적으로 실행할 때와 동일한 결과를 얻게 됨
- 영속성 (Durability)은 트랜잭션이 커밋될 때 시스템 오류가 발생하더라도 모든 데이터가 유지되도록 보장
- 데이터베이스는 앞서 나열한 속성을 모두 충족하고 성공적인 트랜잭션만 처리될 때 ACID를 준수한다고 함
- 트랜잭션이 완료되기 전에 오류가 발생할 경우 ACID 준수는 데이터가 변경되지 않게 보장
- 몽고DB는 복제 셋과 샤드 전체에 ACID 호환 트랜잭션이 있는 분산 데이터베이스
2. 트랜잭션 사용법
- 몽고DB는 트랜잭션을 사용하기 위한 두 가지 API를 제공
- 첫 번째는 코어 API라는 관계형 데이터베이스와 유사한 구문 i.g. start_transaction, commit_transaction
- 두 번째는 트랜잭션 사용에 권장되는 접근 방식인 콜백 AP.I
- 코어 API는 대부분의 오류에 재시도 로직을 제공하지 않으며 개발자가 작업에 대한 로직, 트랜잭션 커밋 함수, 그리고 필요한 재시도 및 오류 로직을 모두 작성해야 함
- 콜백 API는 지정된 논리 세션과 관련된 트랜잭션 시작, 콜백 함수로 제공된 함수 실행, 트랜잭션 커밋 또는 오류 시 중단을 포함해 코어 API에 비해 많은 기능을 Wrapping 하는 단일 함수를 제공
- 해당 함수는 커밋 오류를 처리하는 재시도 로직도 포함
- 콜백 API는 몽고DB 4.2에 추가돼 트랜잭션을 통해 애플리케이션 개발을 단순화하고 트랜잭션 오류를 처리하는 애플리케이션 재시도 로직을 쉽게 추가함
- 두 API에서 개발자는 트랜잭션에서 사용할 논리 세션을 시작해야 하며, 트랜잭션의 작업이 특정 논리 세션과 연결돼야 함
- 몽고DB 논리 세션은 전체 몽고DB 배포 컨텍스트에서 작업의 시간과 순서를 추적
- 논리 세션 또는 서버 세션은 몽고DB에서 재시도 가능한 쓰기와 인과적 일관성을 지원하기 위해 클라이언트 세션에서 사용하는 기본 프레임워크의 일부
- 순서에 따라 인과관계가 반영된 읽기 및 쓰기 작업의 시퀀스는 몽고DB에서 인과관계가 있는 클라이언트 세션으로 정의됨
- 클라이언트 세션은 애플리케이션에 의해 시작되며 서버 세션과 상호작용하는 데 사용됨
- 애플리케이션이 복잡하고 추가 코드 작성이 필요할 때 코어 API보다 콜백 API를 권장
코어 API | 콜백 API |
트랜잭션을 시작하고 커밋하려면 명시적인 호출 필요 | 트랜잭션을 시작하고 지정된 작업을 실행한 뒤 커밋 (오류 시 중단) |
TransientTransactionError 및 UnknownTransactionCommitResult에 대한 오류 처리 로직을 통합하지 않은 대신 사용자 지정 오류 처리를 통합하는 유연성 제공 | TransientTransactionError 및 UnknownTransactionCommitResult에 대한 오류 처리 로직을 자동으로 통합 |
특정 트랜잭션을 위해 API로 전달되는 명시적 논리 세션 필요 |
- 자세한 내용은 [몽고DB의 클러스터 전체 논리 클록과 인과적 일관성 구현] 논문 참고
2.1 코어 API 예제
- 트랜잭션의 두 가지 작업은 아래 프로그램 목록의 Step 1에서 강조됨
2.2 콜백 API 예제
- 트랜잭션의 두 가지 작업은 아래 프로그램 목록의 Step 1에서 강조됨
3. 애플리케이션을 위한 트랜잭션 제한 조정
- 트랜잭션을 사용할 때 숙지해야 할 몇 가지 매개변수가 있음
- 애플리케이션이 트랜잭션을 최적으로 사용하도록 매개변수를 조정해야 함
3.1 타이밍과 Oplog 크기 제한
- 몽고DB 트랜잭션에는 두 가지 주요 제한 범주가 있음
- 첫 번째는 트랜잭션의 시간제한, 즉 특정 트랜잭션이 실행될 수 있는 시간, 트랜잭션이 락을 획득하려고 대기하는 시간, 그리고 모든 트랜잭션이 실행될 최대 길이를 제어하는 것과 관련 있음
- 두 번째 범주는 특히 몽고DB oplog 항목과 개별 항목에 대한 크기 제한과 관련 있음
가. 시간 제한
- 트랜잭션의 최대 실행 시간은 기본적으로 1분 이하
- mongod 인스턴스 레벨에서 transactionLifetimeLimitSeconds에 의해 제어되는 제한을 수정해 증가시킬 수 있음
- 샤드 클러스터의 경우 모든 샤드 복제 셋 멤버에 매개변수를 설정해야 함
- 이 시간이 경과하면 트랜잭션이 만료됐다고 간주하며 주기적으로 실행되는 정리 프로세스에 의해 중단됨
- 정리 프로세스는 min(60초, transactionLifetimeLimitSeconds / 2) 값을 주기로 실행됨
- 트랜잭션에 시간 제한을 명시적으로 설정하려면 commitTransaction에 maxTimeMS를 지정하는 것이 좋음
- maxTimeMS를 설정하지 않으면 transactionLifetimeLimitSeconds가 사용됨
- maxTimeMS를 설정했지만 transactionLifetimeLimitSeconds를 초과하는 경우 transactionLifetimeLimitSeconds가 대신 사용됨
- 트랜잭션의 작업에 필요한 락을 획득하기 위해 트랜잭션이 대기하는 최대 시간은 기본적으로 5ms
- maxTransactionLockRequestTimeoutMillis에 의해 제어되는 제한을 수정해 늘릴 수 있음
- 이 시간 내 락을 획득할 수 없으면 트랜잭션은 중단됨
- maxTransactionLockRequestTimeoutMillis는 0, -1 또는 0보다 큰 숫자로 설정 가능
- 0으로 설정한 경우 필요한 모든 락을 즉시 획득할 수 없으면 트랜잭션이 중단됨
- -1로 설정하면 작업별 제한 시간이 maxTimeMS에 지정된 대로 사용됨
- 0보다 큰 숫자는 트랜잭션이 필요한 락을 획득하려고 시도하는 기간으로 해당 시간까지의 대기 시간을 구성함
나. Oplog 크기 제한
- 몽고DB는 트랜잭션의 쓰기 작업에 필요한 만큼 oplog 항목을 생성하지만 각 oplog 항목은 BSON 도큐먼트 크기 제한인 16MB 이하여야 함
정리
- 트랜잭션은 일관성을 보장하기 위해 몽고DB에서 유용한 기능을 제공하지만 풍부한 도큐먼트 모델과 함께 사용돼야 함
- 유연성 있는 모델과 스키마 설계 패턴과 같은 모범 사례를 사용하면 대부분의 상황에서 트랜잭션을 사용하지 않아도 됨
- 따라서 트랜잭션은 애플리케이션에서 드물게 사용하는 것이 좋은 강력한 기능
참고
몽고DB 완벽 가이드 3판 - 한빛미디어
반응형
'DB > 몽고DB 완벽 가이드 3판' 카테고리의 다른 글
[10장] 복제 셋 설정 (0) | 2025.04.22 |
---|---|
[9장] 애플리케이션 설계 (0) | 2025.04.21 |
[7장] 집계 프레임워크 (0) | 2025.04.12 |
[6장] 특수 인덱스와 컬렉션 유형 (0) | 2025.04.10 |
[5장] 인덱싱 (0) | 2025.04.04 |