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