본문 바로가기

DB/MongoDB

[MongoDB] 16. 집계명령어 - 트랜잭션

728x90
반응형

트랜잭션

  • 읽기나 쓰기 작업이 가능한 DB 작업을 하나 이상 포함하는 DB의 "논리적 처리 단위"
  • 애플리케이션에서 논리적 처리 단위의 일부로 여러 도큐먼트에 대한 읽기와 쓰기를 요구하는 상황 발생 가능성
  • 트랜잭션의 중요한 특징
    • "성공하든 실패하든 부분적으로 완료하지 않는다."
  • 특성
    • Atomicity(원자성) - 트랜잭션의 작업이 모두 적용되거나 아무 작업도 적용되지 않음.
    • Consistency(일관성) - 트랜잭션에 성공하면 DB가 하나의 일관된 상태에서 새로운 일관된 상태로 이동
    • Isolation(독립성) - 여러 트랜잭션이 동시 실행될 때 트랜잭션이 다른 트랜잭션의 부분 결과를 보지 않도록 보장
    • Durability(지속성) - 트랜잭션이 완료되면 어떤 오류나 고장에도 변경된 값은 유지

MongoDB의 트랜잭션

MongoDB는 단일 도큐먼트를 쓰고 수정하고, 삭제하는 작업에서 "원자성"이 성립 한다.

이런 MongoDB에서 트랜잭션을 수행하려면 "세션"을 할당 받아야한다.

  • 세션이란, 일정 시간 같은 사용자로부터 들어오는 일련의 요구를 하나의 상태(단위)로 보고, 그 상태를 일정하게 유지시키는 기술임.

MongoDB에서 트랜잭션을 사용하는데 제약 사항

  • 4.2버전 이상에서만 허용
  • readConcernwriteConcern을 제대로 설정해야만 데이터 손실에 대한 피해를 최소화 가능
  • 명령어에 제한이 있음
  • 도큐먼트 생성, 읽기, 수정, 삭제는 트랜잭션에 포함
  • 컬렉션 생성, 삭제는 트랜잭션에 포함될 수 없음

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
반응형