[MongoDB] locks

DataBase 2014. 2. 1. 17:37




MongoDB는 CAP 모델에서 Availability보다 Concurrency를 중요시 한다.

사용하는 lock은 readers-writer lock이다.

2.2 버전부터 일반적인 read/write lock은 Database 단위이다. (그나마도 2.2 이전에는 global lock이었다)



[lock 상태확인]

lock 상태를 알고 싶다면 아래의 방법을 사용할 수 있다.


mongo 커맨드라인에서 아래의 명령어를 사용하거나,

db.serverStatus()

db.currentOp()


MongoDB bin 디렉토리에 있는 아래 명령어를 사용하거나.

mongotop

mongostat




[yield]

몇몇 상황에서 read/write는 lock을 양보(yield)할 수 있다.

기본적으로 yield가 일어나는 상황은 operation에 해당하는 데이터가 memory에 적재되어 있어 page fault를 일으키지 않는지에 대한 여부이다.

만약 operation에 해당하는 데이터가 memory에 없을 경우 그 데이터가 memory에 적재되는 동안, lock을 다른 in-memory 데이터를 사용할 operation에 넘기고 memory 적재가 완료되면 다시 lock을 가져와 operation을 완료한다는 개념이다.

2.0에선 time slice 기반의 알고리즘이 사용되어, 긴 시간동안 실행되는 read/write는 주기적으로 lock을 양보하는 개념이고,

2.2에선 disk access 가능성을 예측하는 알고리즘이 추가되어, MongoDB가 memory의 content를 추적하면서 read가 일어나기 전 해당 데이터가 memory에 없다고 예상될 경우 해당 read operation은 write에게 lock을 양보하고 데이터를 memory로 적재한 다음 lock을 다시 가져오는 형식이다.





[lock을 일으키는 operation]


 Operation

  Lock Type 

 query

 read lock 

 get more

(cursor로부터 데이터를 더 가져오는 operation)

 read lock

 insert

 write lock 

 remove

 write lock 

 update

 wirte lock 

 Map-Reduce

 read/write lock

 (non-atomic을 제외하고 read/write lock 모두 사용함) 

 index 생성 

 background:true 가 아니라면 제법 긴 시간동안 database 전체 lock 

 db.eval()

 write lock

(다른 모든 JavaScript process를 block 한다) 

 eval

 write lock

(nolock 옵션이 세팅되면 write lock을 사용하지 않으며 database에 아무런 데이터를 write할 수 없음) 

 aggregate()

 read lock 






[admin command의 lock]

몇몇 admin command는 긴 시간동안 database 전체에 exclusive lock을 걸기 때문에,

대형 database일 경우 mongod를 offline 상태로 해놓고 작업할 것을 고려해야한다.

예를 들어, 작업할 mongod instance가 replicaSet의 일부라면, 해당 mongod를 replicaSet에서 떼어낸 후 작업하고,

작업완료 후 다시 replicaSet에 넣음으로써 서비스 동작에는 영향이 없도록 해야한다.


아래의 admin command는 database 전체에 exclusive lock을 건다.

db.collection.ensureIndex() - background:true일 경우 제외.

reIndex

compact

db.repairDatabase()

db.createCollection() - 수 기가바이트의 큰 capped collection 생성의 경우.

db.collection.validate() - 전체 database에 lock을 건다.

db.copyDatabase() - 전체 database에 lock을 건다.





[하나 이상의 lock이 걸리는 경우]

아래 operation은 여러 database에 lock을 건다.

db.copyDatabase() - 모든 mongod instance에 lock을 건다.

Journaling - 모든 database는 하나의 저널을 공유하기 때문에 저널링은 모든 database에 짧은 시간 동안의 lock을 건다.

User Authentication - user가 access하고자 하는 database에 더하여 admin database에도 lock을 건다.

ReplicaSet writes - replicatSet의 write는 1. primary의 write lock, 2. oplog를 local database에 쓰는 lock 이렇게 2개의 lock이 짧은 시간 동안 걸린다.





[lock in sharding]

각 shard는 각자 따로따로 lock을 가지므로 하나의 mongod instance에 걸린 lock은 다른 shard의 operation을 block 시키지 않는다.

그러므로 lock으로 인한 병목이 생긴다면 shard를 늘이는 것으로 어느정도 해결이 가능하다.





[참조]

http://docs.mongodb.org/manual/faq/concurrency














Posted by bloodguy
,