728x90
반응형
트랜잭션
- 읽기나 쓰기 작업이 가능한 DB 작업을 하나 이상 포함하는 DB의 "논리적 처리 단위"
- 애플리케이션에서 논리적 처리 단위의 일부로 여러 도큐먼트에 대한 읽기와 쓰기를 요구하는 상황 발생 가능성
- 트랜잭션의 중요한 특징
- "성공하든 실패하든 부분적으로 완료하지 않는다."
- 특성
- Atomicity(원자성) - 트랜잭션의 작업이 모두 적용되거나 아무 작업도 적용되지 않음.
- Consistency(일관성) - 트랜잭션에 성공하면 DB가 하나의 일관된 상태에서 새로운 일관된 상태로 이동
- Isolation(독립성) - 여러 트랜잭션이 동시 실행될 때 트랜잭션이 다른 트랜잭션의 부분 결과를 보지 않도록 보장
- Durability(지속성) - 트랜잭션이 완료되면 어떤 오류나 고장에도 변경된 값은 유지
MongoDB의 트랜잭션
MongoDB는 단일 도큐먼트를 쓰고 수정하고, 삭제하는 작업에서 "원자성"이 성립 한다.
이런 MongoDB에서 트랜잭션을 수행하려면 "세션"을 할당 받아야한다.
- 세션이란, 일정 시간 같은 사용자로부터 들어오는 일련의 요구를 하나의 상태(단위)로 보고, 그 상태를 일정하게 유지시키는 기술임.
MongoDB에서 트랜잭션을 사용하는데 제약 사항
- 4.2버전 이상에서만 허용
- readConcern과 writeConcern을 제대로 설정해야만 데이터 손실에 대한 피해를 최소화 가능
- 명령어에 제한이 있음
- 도큐먼트 생성, 읽기, 수정, 삭제는 트랜잭션에 포함
- 컬렉션 생성, 삭제는 트랜잭션에 포함될 수 없음
MongoDB의 트랜잭션 사용법
코어 API 사용
- 관계형 DB와 유사한 구문 사용
- 대부분의 오류에 재시도 로직을 제공하지 않음
- 개발자가 작업에 대한 로직, 트랜잭션 완료 함수, 재시도 및 오류 로직을 모두 작성해야 함
콜백 API 사용
- 트랜잭션 사용에 권장되는 접근 방식
- 지정된 논리 세션과 관련된 트랜잭션 시작
- 콜백 함수로 제공된 함수 실행
- 트랜잭션 완료(또는 오류시 중단)을 포함해 코어 API에 비해 많은 기능을 래핑하는 단일 함수 제공
두 API에서 개발자는 트랜잭션에서 사용할 논리 세션을 시작해야하고 트랜잭션의 작업이 특정 논리 세션과 연결되어 있어야함.
코어 API | 콜백 API |
트랜잭션을 시작하고 완료하려면 명시적인 호출이 필요하다. | 트랜잭션을 시작하고 지정된 작업을 실행한 후 완료(또는 중단)한다 |
오류에 대한 로직을 통합하지 않고 대신 사용자 지정 오류 처리를 통합하는 유연성을 제공한다. | 오류 처리 로직을 자동으로 통합한다. |
특정 트랜잭션을 위해 API로 전달되는 명시적 논리 세션을 필요하다. | 특정 트랜잭션을 위해 API로 전달되는 명시 적 논리 세션이 필요하다. |
MongoDB의 트랜잭션 사용해보기
startSession() : 세션 시작
startTransaction() : 트랜잭션 시작
readConcern : 읽기 문제 수준(level)을 지정
- snapshot
- local
- majority
writeConcern : 쓰기 문제(w)를 지정
- majority
commitTransaction() : 트랜잭션 커밋
abortTransaction() : 트랜잭션 커밋
endSession() : 세션 종료
// 100개 넣기 동작
for(i=0;i<100000;i++){
db.user100.insertOne(
{
"i":i,
"usrName":"user"+i,
"age":Math.floor(Math.random()*120),
"created":new Date()
})
}
// 세션 시작
session = db.getMongo().startSession()
// 트랜잭션 시작
session.startTransaction({readConcern : {level:"snapshot"},
writeConcern : {w:"majority"}})
// 수정 작업
db.user100.updateMany({},{$set:{"created":new Date()}})
// 트랜잭션 커밋
session.commitTransaction()
// 세션 종료
session.endSession()
트랜잭션 전
트랜잭션 완료 후
MongoDB의 동시성 제어
다른 DBMS와 마찬가지로 MongoDB도 멀티 쓰레드의 동시 처리중에 발생할 수 있는 충돌 문제를 방지하기 위해 "Lock"을 사용한다.
다중 레벨 잠금(Multi-granularity locking)을 지원함
- 잠금을 획득한다고 해서 해당 컬렉션, DB, 인스턴스에 접근하지 못하는 것은 아님.
네 가지 잠금 수준
- Global - 모든 DB가 잠기는 MongoDB 인스턴스 수준 잠금
- Database - 언급된 데이터베이스가 잠기는 데이터베이스 수준 잠금
- Collection - 컬렉션 수준에서 잠금
- Document - 특정 도큐먼트만 잠기는 수준의 잠금
네 가지 잠금 모드
- Shared(R or S)
- 공유 잠금(읽기 잠금)
- S-Lock
- 현재 쓰레드가 참조하고 있는 데이터를 다른 쓰레드가 변경하지 못하도록 하는 것이 목표
- 다른 쓰레드의 Shared Lock과 호환
- 데이터를 읽기만 하는 경우 여러 쓰레드가 동시에 읽을 수 있음
- Exclusive(W or X)
- 배타적 잠금(쓰기 잠금)
- X-Lock
- 현재 쓰레드가 변경하려고 하는 데이터를 다른 쓰레드가 변경하지 못하게 방지하는 것이 목표
- 변경중인 데이터를 다른 쓰레드가 읽는 것도 허용하지 않음
- Intent Shared(r or IS)
- 내부에 공유 잠금 설정 시
- 하위 수준 잠금 전에 획득한 상위 수준 잠금
- r 잠금이 DB에 적용 시 Lock Holder가 컬렉션 또는 도큐먼트 수준에서 S-Lock을 적용할 의향이 있음을 의미
- Intent Exclusive(w or IE)
- 내부에 독점 잠금 설정 시
- Lock Holder가 세분화된 수준에서 리소스를 수정할 것 임을 나타냄
- w 잠금이 DB에 적용 시 Lock Holder가 컬렉션 또는 도큐먼트 수준에서 X-Lock을 적용할 의향이 있음을 의미
양립성 테이블
보유(세로) \ 요청(가로) | X(W) | IX(w) | S(R) | IS(r) |
X(W) | X | X | X | X |
IX(w) | X | O | X | O |
S(R) | X | X | O | O |
IS(r) | X | O | O | O |
- 인텐션 잠금일 때 독점 잠금은 허용되지 않음
- 공유 잠금과 인텐션 잠금은 허용됨
- 인텐션 잠금들은 호환이 가능
- 호환되지 않은 잠금 요청하는 연산은 "대기" 상태로 들어감
- write conflict : 독점 잠금인 데이터를 수정하려고 할 때는 대기 상태가 아니라 에러 발생 시키고 재시도
트랜잭션은 일관성 보장을 위해 MongoDB에서 유용한 기능을 제공하지만 풍부한 도큐먼트 모델과 같이 사용
유연성 있는 모델, 스키마 설계 패턴과 같은 모범 사례를 사용 시 대부분의 상황에서 트랜잭션 사용하지 않아도 됨
트랜잭션은 애플리케이션에서 드물게 사용하는 것이 좋은 강력한 기능
728x90
반응형
'DB > MongoDB' 카테고리의 다른 글
[MongoDB] 18. 데이터 모델링과 인덱스 - 인덱스 (0) | 2022.12.18 |
---|---|
[MongoDB] 17. 데이터 모델링과 인덱스 - 데이터 모델링 (0) | 2022.12.18 |
[MongoDB] 15. 집계명령어 - 다양한 연산자, 뷰 (0) | 2022.12.17 |
[MongoDB] 14. 집계명령어 - 고급 스테이지, 여러가지 스테이지 (0) | 2022.12.17 |
[MongoDB] 13. 집계명령어 - aggregate, $project, $match, $group (0) | 2022.10.17 |