본문으로 바로가기

과거 포스트를 인용해보겠습니다

(https://darrengwon.tistory.com/223?category=870801)

 

🚧 원자성

원자성이란, 중간의 상태가 없는, 모 아니면 도의 상태만 존재하는 것입니다. 즉, 데이터 처리 전/후 만 존재하는 것이지 데이터 처리 중은 존재하지 않는 것입니다.

 

ATM에 돈을 넣는 도중 전원이 나가 서버가 죽었다고 생각합시다. 이 때 ATM에 넣은 돈은 반영이 된 것인지, 되지 않은 것인지 불명확합니다. 이러한 불상사를 막기 위해 원자성을 추구해야 합니다.

 

insertOne의 경우 원자성을 가지고 있습니다 (당연히 처리해야 할 도큐먼트가 1개 뿐이므로)

 

그러나 insertMany와 같은 다중 작업의 경우 위의 예시에서 살펴볼 수 있듯 원자성을 가지고 있지 않습니다. 원자성이 적용되었다면, 오류가 난 즉시 아무것도 저장이 안되어야 했었는데, {_id: 2, x: 5}가 저장이 되었으니까요.

 

// {_id: 2, x: 5}은 저장되었으나 그 이후는 저장 안됨
db.user.insertMany([{_id: 2, x: 5}, {_id: 2, x : 7}, {_id: 3, x : 9}])

 

mongoDB에서는 이러한 원자성을 성립하게 만들어주기 위해 '트랜잭션(Transaction) 기능을 지원합니다. (4.0 버전 이상 부터 가능)

 


 

Transactions — MongoDB Manual

The example uses the new callback API for working with transactions, which starts a transaction, executes the specified operations, and commits (or aborts on error). The new callback API also incorporates retry logic for TransientTransactionError or Unknow

docs.mongodb.com

 

정리하자면, 단일 도큐먼트에서는 원자성이 성립하나 여러 개의 도큐먼트를 CRUD하는 경우에는 원자성이 성립하지 않는다는 것입니다. 여러 도큐먼트에서 원자성을 유지하기 위해서는 트랜잭션이 필요합니다.

 

1️⃣세션을 생성한 후

2️⃣startTransaction 메서드로 트랜잭션을 시작하며

3️⃣트랜잭션으로 묶고 싶은 내용들을 처리하고

4️⃣commitTransaction 메서드로 트랜잭션을 닫고

5️⃣세션을 종료합니다.

 

생각보다 간단하네요. 코드로 구현하면 다음과 같다고 합니다.

 

session = db.getMongo().startSession()
session.startTransaction({readConcern: {level: 'snapshot'}, writeConcern: {w: 'majority'}});

// 수행하기 원하는 작업들

session.commitTransaction();
session.endSession();

 

트랜잭션으로 처리할 수 있는 작업은 도큐먼트를 CRUD하는 것만 가능하며 컬렉션을 생성하는 등 도큐먼트 레벨을 벗어나는 작업은 할 수 없습니다.

 

 

🚧 WriteConcern, ReadConcern 옵션

 

  WriteConcern은 insertOne, insertMany 등의 명령어를 통해 도큐먼트를 컬렉션에 넣으려고 할 때 해당 컬렉션이 쓰기작업(도큐먼트 생성, 수정, 삭제) 중이라면 어떻게 할 것인지에 대한 것입니다.

  ReadConern은 find 명령어를 통해 읽기 작업을 할 때 더 정확한 값을 얻어오기 위한 설정값이다.

 

  이러한 설정은 꼼꼼하고 보수적으로 데이터를 다룰 수 있다는 장점이 있지만 성능이 떨어진다는 문제가 있다.

 

 

https://docs.mongodb.com/manual/reference/method/Session.startTransaction/

{ readConcern: { level: <level>}, writeConcern: { w: <value>, j: <boolean>, wtimeout: <number> } }

 

 

 

readConcern의 level에 줄 수 있는 값은 다음과 같습니다.

https://docs.mongodb.com/manual/reference/read-concern/

 

You can specify one of the following read concern levels:

 

witeConcern에 할당하는 w, j, wtimeout에 대한 설명은 다음과 같습니다.

https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.%3Cnumber%3E

 

  • the w option to request acknowledgment that the write operation has propagated to a specified number of mongod instances or to mongod instances with specified tags.
  • the j option to request acknowledgment that the write operation has been written to the on-disk journal, and
  • the wtimeout option to specify a time limit to prevent write operations from blocking indefinitely.

 

 

 

🚨 주의점

 

1. readConcern과 wrtieConcern은 startTranscation에 설정해야 합니다. 트랜잭션 전체에 대한 설정이기 때문에 수행하는 제각각의 명령에 설정하면 안됩니다.

 

 

2. 복제된 서버 환경에서는 4.0 이상부터 트랜잭션을 사용할 수 있고, 샤딩된 환경에서는 4.2 이상부터 트랜잭션을 사용할 수 있습니다.


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체