Database/MongoDB 실습

[MongoDB] 글로벌 잠금 설정과 해제방법

꽁담 2024. 8. 21. 09:35

 

 

1. MongoDB 잠금

MongoDB 서버에서는 멀티 쓰레드의 동시 처리 중에 발생할 수 있는 쓰레드 간의 충돌 문제를 방지하기 위해 잠금을 사용한다.

 

1-1. MongoDB 잠금유형

유형 설명
묵시적 잠금 쿼리가 실행될 때 자동으로 획득했다 해제되는 잠금
명시적 잠금 사용자가 명령어로 잠금을 획득

 

 

2. MongoDB 테스트 버전

유형 버전 구성
mongosh 2.2.10  
mongodb 7.0.12 Config : 1개, 포트 20000
Route : 1개, 포트 20001
Shard1 : 1개, 포트 30001
Shard2 : 1개, 포트 40001

 

 

3. 글로벌 잠금 획득 해제

3-1. fsyncLock 로 획득

fsyncLock 은 글로벌 잠금을 획득하는 함수이다.

MongoDB 서버 인스턴스에 단 하나만 있는 잠금으로, 이를 인스턴스 잠금이라고 한다.

아래와 같은 명령어로 잠금을 획득할 수 있다.

db.fsyncLock( { fsync : 1, lock : true } )

 

fsync 옵션을 1로 설정하면 디스크에 기록되지 못한 데이터를 모두 디스크로 플러시한다.

lock 옵션이 true 이면 글로벌 잠금을 획득한다. 만약 false 면 데이터파일만 디스크로 플러시하고 잠금을 걸지는 않는다.

 

3-2. fsyncUnLock 으로 해제

fsyncUnLock 으로 글로벌 잠금을 해제한다.

db.fsyncUnlock()

 

 

4. 글로벌 잠금 lock=true 테스트

4-1. Session1 적재

글로벌잠금이 활성화 되기 전 적재가 잘 되고 있다.

[direct: mongos] fsyncDB> db.fsynCollection.insert( { "id" : 1, "description" : "Before fsyncLock" } )
DeprecationWarning: Collection.insert() is deprecated. Use insertOne, insertMany, or bulkWrite.
{
  acknowledged: true,
  insertedIds: { '0': ObjectId('66c52b881b30070ca91b157d') }
}

 

4-2. Session 2 글로벌잠금 획득

fsyncLock 함수를 사용하여 글로벌 잠금을 획득한다.

글로벌잠금을 획득하면 info 에 now locked against writes 가 출력된다.

[direct: mongos] test> db.fsyncLock( { fsync : 1, lock : true } )
{
  numFiles: 1,
  all: {
    raw: {
      'rs2/127.0.0.1:40001': {
        info: 'now locked against writes, use db.fsyncUnlock() to unlock',
        lockCount: Long('1'),
        seeAlso: 'http://dochub.mongodb.org/core/fsynccommand',
        ok: 1
      },
      'rs1/127.0.0.1:30001': {
        info: 'now locked against writes, use db.fsyncUnlock() to unlock',
        lockCount: Long('1'),
        seeAlso: 'http://dochub.mongodb.org/core/fsynccommand',
        ok: 1
      },
      'configRepl/127.0.0.1:20000': {
        info: 'now locked against writes, use db.fsyncUnlock() to unlock',
        lockCount: Long('1'),
        seeAlso: 'http://dochub.mongodb.org/core/fsynccommand',
        ok: 1
      }
    }
  },
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1724197771, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1724197771, i: 1 })
}

 

참고로 글로벌잠금을 획득한 세션도 쓰기를 할 수 없다.

[direct: mongos] fsyncDB> db.fsynCollection.insert( { "id" : 3, "description" : "Global Lock Session" } )

 

4-3. Session 1 적재대기

이제 아래의 적재 명령어는 완료되지 못하고 대기하게 된다.

[direct: mongos] fsyncDB> db.fsynCollection.insert( { "id" : 2, "description" : "After fsyncLock" } )

 

 

4-5. Session 3 조회가능

같은 컬렉션과 다른 데이터베이스의 컬렉션을 조회할 때 모두 대기가 발생하지 않고 바로 조회된다.

[direct: mongos] fsyncDB> db.fsynCollection.find()
[
  {
    _id: ObjectId('66c52b881b30070ca91b157d'),
    id: 1,
    description: 'Before fsyncLock'
  }
]


[direct: mongos] fsyncDB> use indexDB()
switched to db indexDB

[direct: mongos] indexDB> db.ttlIndex.find()
[
  {
    _id: ObjectId('66baf3d401027809e11b1585'),
    Number: 4,
    createdAt: 'Sample String'
  },
  {
    _id: ObjectId('66bb014c28fe1d22af1b157e'),
    Number: 1,
    createdAt: '2024-08-10T05:42:36.666Z'
  }
]

 

4-6. Session 2 글로벌잠금 해제

글로벌 잠금을 해제한다.

[direct: mongos] test> db.fsyncUnlock()
{
  raw: {
    'rs2/127.0.0.1:40001': { info: 'fsyncUnlock completed', lockCount: Long('1'), ok: 1 },
    'configRepl/127.0.0.1:20000': { info: 'fsyncUnlock completed', lockCount: Long('1'), ok: 1 },
    'rs1/127.0.0.1:30001': { info: 'fsyncUnlock completed', lockCount: Long('1'), ok: 1 }
  },
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1724197771, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1724197771, i: 1 })
}

 

4-7. Session 1 적재

글로벌잠금이 해제될 때 적재가 시도된 Session 1 의 적재가 완료된다.

[direct: mongos] fsyncDB> db.fsynCollection.insert( { "id" : 2, "description" : "After fsyncLock" } )

 

 

5. 글로벌 잠금 lock=false 테스트

5-1. Session2 글로벌잠금 획득

[direct: mongos] test> db.fsyncLock( { fsync : 1, lock : false } )
{
  numFiles: 1,
  all: {
    raw: {
      'rs2/127.0.0.1:40001': {
        info: 'now locked against writes, use db.fsyncUnlock() to unlock',
        lockCount: Long('1'),
        seeAlso: 'http://dochub.mongodb.org/core/fsynccommand',
        ok: 1
      },
      'configRepl/127.0.0.1:20000': {
        info: 'now locked against writes, use db.fsyncUnlock() to unlock',
        lockCount: Long('1'),
        seeAlso: 'http://dochub.mongodb.org/core/fsynccommand',
        ok: 1
      },
      'rs1/127.0.0.1:30001': {
        info: 'now locked against writes, use db.fsyncUnlock() to unlock',
        lockCount: Long('1'),
        seeAlso: 'http://dochub.mongodb.org/core/fsynccommand',
        ok: 1
      }
    }
  },
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1724201731, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1724201731, i: 1 })
}

 

5-2. Session1 적재대기

여전히 적재는 대기한다. 스터디하는 책의 설명과는 다른부분이 있어 7버전에서는 변경되었나 싶다.

참고로 아래 6. 에서 설명하는 currentOp 에서 fsyncLock 필드값은 true 로 되어있다.

[direct: mongos] fsyncDB> db.fsynCollection.insert( { "id" : 4, "description" : "After fsyncLock lock=false" } )

 

 

6. 글로벌 잠금 설정 확인

currentOp 명령으로 확인이 가능하다. 필드명중 fsyncLock 이 true 값을 가진다.

만약 글로벌잠금이 해제되어 있다면 fsyncLock 필드가 조회되지 않는다.

[direct: mongos] fsyncDB> db.currentOp()
{
  inprog: [
    {
      shard: 'rs2',
      fsyncLock: true,
      type: 'op',
      host: 'ip-172-31-7-169.ap-northeast-2.compute.internal:40001',
      desc: 'Checkpointer',
      active: true,
      currentOpTime: '2024-08-21T00:26:38.863+00:00',
      opid: 'rs2:28779150',
      op: 'none',
      ns: '',
      redacted: false,
      command: {},
      numYields: 0,
      locks: {},
      waitingForLock: false,
      lockStats: {},
      waitingForFlowControl: false,
      flowControlStats: {}
    },
    {
      shard: 'rs2',
      fsyncLock: true,
      type: 'op',
      host: 'ip-172-31-7-169.ap-northeast-2.compute.internal:40001',
      desc: 'OplogCapMaintainerThread-local.oplog.rs',
      active: true,
      currentOpTime: '2024-08-21T00:26:38.863+00:00',
      opid: 'rs2:17',
      op: 'none',
      ns: '',
      redacted: false,
      command: {},
      numYields: 0,
      locks: {},
      waitingForLock: false,
      lockStats: {
        FeatureCompatibilityVersion: { acquireCount: { w: Long('1') } },
        ReplicationStateTransition: { acquireCount: { w: Long('1') } },
        Global: { acquireCount: { w: Long('1') } }
      },
      waitingForFlowControl: false,
      flowControlStats: {}
    },
    {
      shard: 'rs2',
      fsyncLock: true,

...
}