Database/MongoDB 실습

[MongoDB] Yield 잠금 테스트

꽁담 2024. 8. 21. 18:04

 

1. MongoDB Yield 잠금

MongoDB 는 쿼리를 실행하는 도중 잠깐 쉬었다 실행을 재개한다.

이 때 잠금과 스냅샷을 모두 해제하고 지정된 시간동안 쉬다 다시 잠금을 획득 후 다음 실행을 이어가게 된다.

이는 트랜잭션의 동시성 처리를 우수하게 만들기 위함이다.

 

2. MongoDB 테스트 버전

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

 

 

3. Yield 와 관련된 설정 값

Yield 에서 특정 건수를 읽으면 특정 시간을 쉬는데

internalQueryExecYieldPeriodMS 와 internalQueryExecYieldIterations 값을 기준으로 이뤄진다.

 

기본값은 1000 건을 읽으면 10ms 를 쉬게된다.

# 특정 건수를 읽으면
[direct: mongos] test> db.adminCommand( { getParameter : 1, "internalQueryExecYieldIterations" : 1 } )
{
  internalQueryExecYieldIterations: 1000,
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1724230607, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1724230607, i: 1 })
}

# 특정 시간을 쉰다.
[direct: mongos] test> db.adminCommand( { getParameter : 1, "internalQueryExecYieldPeriodMS" : 1 } )
{
  internalQueryExecYieldPeriodMS: 10,
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1724230578, i: 2 }),
    signature: {
      hash: Binary.createFromBase64('AAAAAAAAAAAAAAAAAAAAAAAAAAA=', 0),
      keyId: Long('0')
    }
  },
  operationTime: Timestamp({ t: 1724230578, i: 2 })
}

 

 

4. Yield 테스트

Yield 테스트는 대량의 데이터가 있는경우에 가능하다.

 

4-1. Session 1 에서 데이터 적재

데이터 1만건을 적재한다.

[direct: mongos] transactionDB> for (var idx=0; idx<10000; idx++) { db.consistency.insert ( { fd : idx } ) } ; 
{
  acknowledged: true,
  insertedIds: { '0': ObjectId('66c69fc8e648fd165b1b3c8c') }
}

 

4-2. Session 1 에서 미정렬 데이터 조회

find 명령을 이용하여 풀 스캔 조회하면 모두 출력하지 않고 커서를 반환하므로 20건만 출력한다.

분명히 find 명령을 사용하였으므로 풀스캔인 상태이나 Yield 에 의해 

[direct: mongos] transactionDB> db.consistency.find()
[
  { _id: ObjectId('66c69fa0e648fd165b1b157d'), fd: 0 },
  { _id: ObjectId('66c69fa0e648fd165b1b157e'), fd: 1 },
  { _id: ObjectId('66c69fa0e648fd165b1b157f'), fd: 2 },
  { _id: ObjectId('66c69fa0e648fd165b1b1580'), fd: 3 },
  { _id: ObjectId('66c69fa0e648fd165b1b1581'), fd: 4 },
  { _id: ObjectId('66c69fa0e648fd165b1b1582'), fd: 5 },
  { _id: ObjectId('66c69fa0e648fd165b1b1583'), fd: 6 },
  { _id: ObjectId('66c69fa0e648fd165b1b1584'), fd: 7 },
  { _id: ObjectId('66c69fa0e648fd165b1b1585'), fd: 8 },
  { _id: ObjectId('66c69fa0e648fd165b1b1586'), fd: 9 },
  { _id: ObjectId('66c69fa0e648fd165b1b1587'), fd: 10 },
  { _id: ObjectId('66c69fa0e648fd165b1b1588'), fd: 11 },
  { _id: ObjectId('66c69fa0e648fd165b1b1589'), fd: 12 },
  { _id: ObjectId('66c69fa0e648fd165b1b158a'), fd: 13 },
  { _id: ObjectId('66c69fa0e648fd165b1b158b'), fd: 14 },
  { _id: ObjectId('66c69fa0e648fd165b1b158c'), fd: 15 },
  { _id: ObjectId('66c69fa0e648fd165b1b158d'), fd: 16 },
  { _id: ObjectId('66c69fa0e648fd165b1b158e'), fd: 17 },
  { _id: ObjectId('66c69fa0e648fd165b1b158f'), fd: 18 },
  { _id: ObjectId('66c69fa0e648fd165b1b1590'), fd: 19 }
]
Type "it" for more

 

4-3. Session 2 에서 데이터 삭제

다른 세션에서 fd 가 50인 데이터를 삭제한다.

[direct: mongos] transactionDB> db.consistency.remove ( { fd : 50 } )
{ acknowledged: true, deletedCount: 1 }

 

4-4. Session 1 에서 데이터 조회

find 호출이 계속되고 있지만 it 으로 다음결과를 가져올 때 50의 값을 조회하지 못한다.

이는 잠금이 해제되기 때문이다.

[direct: mongos] transactionDB> it
[
  { _id: ObjectId('66c69fa0e648fd165b1b1591'), fd: 20 },
  { _id: ObjectId('66c69fa0e648fd165b1b1592'), fd: 21 },
  { _id: ObjectId('66c69fa0e648fd165b1b1593'), fd: 22 },
  { _id: ObjectId('66c69fa0e648fd165b1b1594'), fd: 23 },
  { _id: ObjectId('66c69fa0e648fd165b1b1595'), fd: 24 },
  { _id: ObjectId('66c69fa0e648fd165b1b1596'), fd: 25 },
  { _id: ObjectId('66c69fa0e648fd165b1b1597'), fd: 26 },
  { _id: ObjectId('66c69fa0e648fd165b1b1598'), fd: 27 },
  { _id: ObjectId('66c69fa0e648fd165b1b1599'), fd: 28 },
  { _id: ObjectId('66c69fa0e648fd165b1b159a'), fd: 29 },
  { _id: ObjectId('66c69fa0e648fd165b1b159b'), fd: 30 },
  { _id: ObjectId('66c69fa0e648fd165b1b159c'), fd: 31 },
  { _id: ObjectId('66c69fa0e648fd165b1b159d'), fd: 32 },
  { _id: ObjectId('66c69fa0e648fd165b1b159e'), fd: 33 },
  { _id: ObjectId('66c69fa0e648fd165b1b159f'), fd: 34 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a0'), fd: 35 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a1'), fd: 36 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a2'), fd: 37 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a3'), fd: 38 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a4'), fd: 39 }
]
Type "it" for more
[direct: mongos] transactionDB> it
[
  { _id: ObjectId('66c69fa0e648fd165b1b15a5'), fd: 40 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a6'), fd: 41 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a7'), fd: 42 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a8'), fd: 43 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a9'), fd: 44 },
  { _id: ObjectId('66c69fa0e648fd165b1b15aa'), fd: 45 },
  { _id: ObjectId('66c69fa0e648fd165b1b15ab'), fd: 46 },
  { _id: ObjectId('66c69fa0e648fd165b1b15ac'), fd: 47 },
  { _id: ObjectId('66c69fa0e648fd165b1b15ad'), fd: 48 },
  { _id: ObjectId('66c69fa0e648fd165b1b15ae'), fd: 49 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b0'), fd: 51 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b1'), fd: 52 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b2'), fd: 53 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b3'), fd: 54 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b4'), fd: 55 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b5'), fd: 56 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b6'), fd: 57 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b7'), fd: 58 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b8'), fd: 59 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b9'), fd: 60 }
]
Type "it" for more

 

4-5. Session 1 에서 정렬 데이터 조회

정렬을 사용하는 경우에는 모든 데이터를 메모리에 올려놓고 진행된다.

메모리에 올라간 데이터는 정렬버퍼(메모리)에 임시로 복사된 결과에 적용되지 않기에 일관된 결과를 보여준다.

[direct: mongos] transactionDB> db.consistency.find().sort({fd:1})
[
  { _id: ObjectId('66c69fa0e648fd165b1b157d'), fd: 0 },
  { _id: ObjectId('66c69fa0e648fd165b1b157e'), fd: 1 },
  { _id: ObjectId('66c69fa0e648fd165b1b157f'), fd: 2 },
  { _id: ObjectId('66c69fa0e648fd165b1b1580'), fd: 3 },
  { _id: ObjectId('66c69fa0e648fd165b1b1581'), fd: 4 },
  { _id: ObjectId('66c69fa0e648fd165b1b1582'), fd: 5 },
  { _id: ObjectId('66c69fa0e648fd165b1b1583'), fd: 6 },
  { _id: ObjectId('66c69fa0e648fd165b1b1584'), fd: 7 },
  { _id: ObjectId('66c69fa0e648fd165b1b1585'), fd: 8 },
  { _id: ObjectId('66c69fa0e648fd165b1b1586'), fd: 9 },
  { _id: ObjectId('66c69fa0e648fd165b1b1587'), fd: 10 },
  { _id: ObjectId('66c69fa0e648fd165b1b1588'), fd: 11 },
  { _id: ObjectId('66c69fa0e648fd165b1b1589'), fd: 12 },
  { _id: ObjectId('66c69fa0e648fd165b1b158a'), fd: 13 },
  { _id: ObjectId('66c69fa0e648fd165b1b158b'), fd: 14 },
  { _id: ObjectId('66c69fa0e648fd165b1b158c'), fd: 15 },
  { _id: ObjectId('66c69fa0e648fd165b1b158d'), fd: 16 },
  { _id: ObjectId('66c69fa0e648fd165b1b158e'), fd: 17 },
  { _id: ObjectId('66c69fa0e648fd165b1b158f'), fd: 18 },
  { _id: ObjectId('66c69fa0e648fd165b1b1590'), fd: 19 }
]
Type "it" for more

 

4-6. Session 2 에서 데이터 삭제

다른 세션에서 fd 가 70인 데이터를 삭제한다.

[direct: mongos] transactionDB> db.consistency.remove ( { fd : 70 } )
{ acknowledged: true, deletedCount: 1 }

 

4-7. Session 1 에서 데이터 조회

이번에는 70 의 값이 메모리에 상주해 있기 때문에 계속 조회할 수 있다.

[direct: mongos] transactionDB> it
[
  { _id: ObjectId('66c69fa0e648fd165b1b1591'), fd: 20 },
  { _id: ObjectId('66c69fa0e648fd165b1b1592'), fd: 21 },
  { _id: ObjectId('66c69fa0e648fd165b1b1593'), fd: 22 },
  { _id: ObjectId('66c69fa0e648fd165b1b1594'), fd: 23 },
  { _id: ObjectId('66c69fa0e648fd165b1b1595'), fd: 24 },
  { _id: ObjectId('66c69fa0e648fd165b1b1596'), fd: 25 },
  { _id: ObjectId('66c69fa0e648fd165b1b1597'), fd: 26 },
  { _id: ObjectId('66c69fa0e648fd165b1b1598'), fd: 27 },
  { _id: ObjectId('66c69fa0e648fd165b1b1599'), fd: 28 },
  { _id: ObjectId('66c69fa0e648fd165b1b159a'), fd: 29 },
  { _id: ObjectId('66c69fa0e648fd165b1b159b'), fd: 30 },
  { _id: ObjectId('66c69fa0e648fd165b1b159c'), fd: 31 },
  { _id: ObjectId('66c69fa0e648fd165b1b159d'), fd: 32 },
  { _id: ObjectId('66c69fa0e648fd165b1b159e'), fd: 33 },
  { _id: ObjectId('66c69fa0e648fd165b1b159f'), fd: 34 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a0'), fd: 35 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a1'), fd: 36 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a2'), fd: 37 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a3'), fd: 38 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a4'), fd: 39 }
]
Type "it" for more
[direct: mongos] transactionDB> it
[
  { _id: ObjectId('66c69fa0e648fd165b1b15a5'), fd: 40 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a6'), fd: 41 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a7'), fd: 42 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a8'), fd: 43 },
  { _id: ObjectId('66c69fa0e648fd165b1b15a9'), fd: 44 },
  { _id: ObjectId('66c69fa0e648fd165b1b15aa'), fd: 45 },
  { _id: ObjectId('66c69fa0e648fd165b1b15ab'), fd: 46 },
  { _id: ObjectId('66c69fa0e648fd165b1b15ac'), fd: 47 },
  { _id: ObjectId('66c69fa0e648fd165b1b15ad'), fd: 48 },
  { _id: ObjectId('66c69fa0e648fd165b1b15ae'), fd: 49 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b0'), fd: 51 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b1'), fd: 52 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b2'), fd: 53 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b3'), fd: 54 },
  { _id: ObjectId('66c69fa0e648fd165b1b15b4'), fd: 55 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b5'), fd: 56 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b6'), fd: 57 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b7'), fd: 58 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b8'), fd: 59 },
  { _id: ObjectId('66c69fa1e648fd165b1b15b9'), fd: 60 }
]
Type "it" for more
[direct: mongos] transactionDB> it
[
  { _id: ObjectId('66c69fa1e648fd165b1b15ba'), fd: 61 },
  { _id: ObjectId('66c69fa1e648fd165b1b15bb'), fd: 62 },
  { _id: ObjectId('66c69fa1e648fd165b1b15bc'), fd: 63 },
  { _id: ObjectId('66c69fa1e648fd165b1b15bd'), fd: 64 },
  { _id: ObjectId('66c69fa1e648fd165b1b15be'), fd: 65 },
  { _id: ObjectId('66c69fa1e648fd165b1b15bf'), fd: 66 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c0'), fd: 67 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c1'), fd: 68 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c2'), fd: 69 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c3'), fd: 70 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c4'), fd: 71 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c5'), fd: 72 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c6'), fd: 73 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c7'), fd: 74 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c8'), fd: 75 },
  { _id: ObjectId('66c69fa1e648fd165b1b15c9'), fd: 76 },
  { _id: ObjectId('66c69fa1e648fd165b1b15ca'), fd: 77 },
  { _id: ObjectId('66c69fa1e648fd165b1b15cb'), fd: 78 },
  { _id: ObjectId('66c69fa1e648fd165b1b15cc'), fd: 79 },
  { _id: ObjectId('66c69fa1e648fd165b1b15cd'), fd: 80 }
]
Type "it" for more