MongoDB 7.0.6 기준
oplog는 MongoDB의 replicaSet에서 데이터 동기화를 위해 primary 노드에서 발생한 모든 데이터 변경 작업을 기록하여 secondary 노드로 전파하여 데이터의 일관성을 유지하기 위한 로그.
oplog의 일반적인 포맷은 아래와 같음.
// insertOne()에 대한 oplog 예제.
{
// Logical Session ID (
lsid: {
id: UUID('72e4e59b-84d9-4aa0-9830-39173b08087f'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
// Transaction Number (세션 내에서 실행된 트랜잭션 번호. 동일 트랜잭션일 경우 같은 번호)
txnNumber: Long('10'),
// 실행된 명령 유형 (i=insert, u=update, d=delete, n=no-op, c=command)
op: 'i',
// namespace
ns: 'my_service.users',
// collection unique id
ui: UUID('d2c39f44-ec4e-41e7-93f5-94abbd29cd8b'),
// 실행된 주 object
o: { _id: ObjectId('6656d168798ce72b3fdb83bc'), name: '백충덕', age: 99 },
// query object. update의 경우 조건문에 해당
o2: { name: '백충덕', age: 99, _id: ObjectId('6656d168798ce72b3fdb83bc') },
// Statement ID. 트랜잭션 내에서 실행된 명령문 번호=순서
stmtId: 0,
// timestamp
ts: Timestamp({ t: 1716965736, i: 171 }),
// Term. replicaSet이 시작된 이후 몇 번의 선출(election)이 있었는지 나타내는 숫자
t: Long('4'),
// oplog 버전
v: Long('2'),
// ts의 t값을 알아보기 쉽게 ISODate()로 변환한 값
wall: ISODate('2024-05-29T06:55:36.703Z'),
// 트랜잭션 내에서 이전 작업의 ts
prevOpTime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') }
}
op별 oplog.
service 라는 DB를 생성하고 users라는 collection 생성부터 각종 명령 실행마다의 예제임.
// 컬렉션 생성
// _________________________________________________________________________
db.createCollection('users', {
validator:{
$jsonSchema:{
bsonType:'object',
title:'shard key',
required:['name','age'],
properties:{
name:{
bsonType:'string'
},
age:{
bsonType:'int'
}
}
}
}
})
// oplog
{
op: 'c',
ns: 'service.$cmd',
ui: UUID('1cb735b8-a758-4708-b8a2-c45e07367143'),
o: {
create: 'users',
validator: {
'$jsonSchema': {
bsonType: 'object',
title: 'shard key',
required: [ 'name', 'age' ],
properties: { name: { bsonType: 'string' }, age: { bsonType: 'int' } }
}
},
idIndex: { v: 2, key: { _id: 1 }, name: '_id_' }
},
ts: Timestamp({ t: 1716967002, i: 2 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:16:42.914Z')
}
// 인덱스 생성
// _________________________________________________________________________
db.users.createIndex({name:1, age:1})
// oplog
{
op: 'c',
ns: 'service.$cmd',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: {
createIndexes: 'users',
v: 2,
key: { name: 1, age: 1 },
name: 'name_1_age_1'
},
ts: Timestamp({ t: 1716967885, i: 20 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:31:25.060Z')
}
// sharding
// _________________________________________________________________________
sh.shardCollection('service.users', {name:1,age:1})
// oplog
{
op: 'n',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { msg: { shardCollectionPrepare: 'service.users' } },
o2: {
shards: [ 'shard0001' ],
shardCollectionPrepare: 'service.users',
shardKey: { name: 1, age: 1 },
unique: false,
numInitialChunks: Long('0'),
presplitHashedZones: false
},
ts: Timestamp({ t: 1716968001, i: 196 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:33:21.817Z')
},
{
op: 'n',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { msg: { shardCollection: 'service.users' } },
o2: {
shardCollection: 'service.users',
shardKey: { name: 1, age: 1 },
unique: false,
numInitialChunks: Long('0'),
presplitHashedZones: false
},
ts: Timestamp({ t: 1716968001, i: 200 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:33:21.822Z')
}
// insertOne
// _________________________________________________________________________
db.users.insertOne({name:'백충덕', age:99})
// oplog
{
lsid: {
id: UUID('e573bc34-6e6c-4d27-b858-083de253605e'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
txnNumber: Long('1'),
op: 'i',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { _id: ObjectId('6656da8b798ce72b3fdb83c3'), name: '백충덕', age: 99 },
o2: { name: '백충덕', age: 99, _id: ObjectId('6656da8b798ce72b3fdb83c3') },
stmtId: 0,
ts: Timestamp({ t: 1716968075, i: 128 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:34:35.599Z'),
prevOpTime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') }
}
// insertMany
// _________________________________________________________________________
db.users.insertMany([
{name: '조조', age: 10},
{name: '관우', age: 20}
])
// oplog
{
lsid: {
id: UUID('e573bc34-6e6c-4d27-b858-083de253605e'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
txnNumber: Long('2'),
op: 'i',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { _id: ObjectId('6656dace798ce72b3fdb83c4'), name: '조조', age: 10 },
o2: { name: '조조', age: 10, _id: ObjectId('6656dace798ce72b3fdb83c4') },
stmtId: 0,
ts: Timestamp({ t: 1716968142, i: 8 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:35:42.065Z'),
prevOpTime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') }
},
{
lsid: {
id: UUID('e573bc34-6e6c-4d27-b858-083de253605e'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
txnNumber: Long('2'),
op: 'i',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { _id: ObjectId('6656dace798ce72b3fdb83c5'), name: '관우', age: 20 },
o2: { name: '관우', age: 20, _id: ObjectId('6656dace798ce72b3fdb83c5') },
stmtId: 1,
ts: Timestamp({ t: 1716968142, i: 9 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:35:42.065Z'),
prevOpTime: { ts: Timestamp({ t: 1716968142, i: 8 }), t: Long('4') }
}
// updateOne
// _________________________________________________________________________
db.users.updateOne({name:'백충덕'}, {$set:{lv: 1}})
// oplog
{
lsid: {
id: UUID('e573bc34-6e6c-4d27-b858-083de253605e'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
txnNumber: Long('4'),
op: 'u',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
// 존재하지 않던 필드가 추가되었으므로 o.diff.i
o: { '$v': 2, diff: { i: { lv: 1 } } },
o2: { name: '백충덕', age: 99, _id: ObjectId('6656da8b798ce72b3fdb83c3') },
stmtId: 0,
ts: Timestamp({ t: 1716968256, i: 35 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:37:36.320Z'),
prevOpTime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') }
}
db.users.updateOne({name:'백충덕'}, {$set:{lv: 2}})
// oplog
{
lsid: {
id: UUID('e573bc34-6e6c-4d27-b858-083de253605e'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
txnNumber: Long('5'),
op: 'u',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
// 존재하던 필드가 변경되었으므로 o.diff.u
o: { '$v': 2, diff: { u: { lv: 2 } } },
o2: { name: '백충덕', age: 99, _id: ObjectId('6656da8b798ce72b3fdb83c3') },
stmtId: 0,
ts: Timestamp({ t: 1716968391, i: 45 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:39:51.388Z'),
prevOpTime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') }
}
db.users.updateOne({name:'백충덕'}, {$inc:{lv: 1}})
// oplog
{
lsid: {
id: UUID('e573bc34-6e6c-4d27-b858-083de253605e'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
txnNumber: Long('9'),
op: 'u',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
// $inc 되었어도 o.diff.u 를 통해 변경되어야 하는 값으로 세팅됨 = 멱등성 보장 (idempotent) = 해당 oplog 몇번을 실행해도 결과는 동일
o: { '$v': 2, diff: { u: { lv: 3 } } },
o2: { name: '백충덕', age: 99, _id: ObjectId('6656da8b798ce72b3fdb83c3') },
stmtId: 0,
ts: Timestamp({ t: 1716968702, i: 15 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:45:02.157Z'),
prevOpTime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') }
}
db.users.updateOne({name: '백충덕'}, {$unset:{lv: ''}})
// oplog
{
lsid: {
id: UUID('e573bc34-6e6c-4d27-b858-083de253605e'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
txnNumber: Long('11'),
op: 'u',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
// 존재하던 필드가 사라졌으므로 o.diff.d
o: { '$v': 2, diff: { d: { lv: false } } },
o2: { name: '백충덕', age: 99, _id: ObjectId('6656da8b798ce72b3fdb83c3') },
stmtId: 0,
ts: Timestamp({ t: 1716968808, i: 69 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:46:48.385Z'),
prevOpTime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') }
}
// updateMany
// _________________________________________________________________________
db.users.updateMany({}, {$set:{lv:10}})
// oplog
// atomic을 보장하기 위해 조건에 해당하는 document당 1회씩 업데이트가 일어남
// 이런 이유로 명령실행수와 oplog수가 1:1이 아니게 되므로 보관가능한 oplog 범위가 예상과 크게 벗어날 가능성 있음
{
op: 'u',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { '$v': 2, diff: { i: { lv: 10 } } },
o2: { name: '백충덕', age: 99, _id: ObjectId('6656da8b798ce72b3fdb83c3') },
ts: Timestamp({ t: 1716968853, i: 123 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:47:33.644Z')
},
{
op: 'u',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { '$v': 2, diff: { i: { lv: 10 } } },
o2: { name: '조조', age: 10, _id: ObjectId('6656dace798ce72b3fdb83c4') },
ts: Timestamp({ t: 1716968853, i: 124 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:47:33.645Z')
},
{
op: 'u',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { '$v': 2, diff: { i: { lv: 10 } } },
o2: { name: '관우', age: 20, _id: ObjectId('6656dace798ce72b3fdb83c5') },
ts: Timestamp({ t: 1716968853, i: 125 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T07:47:33.645Z')
}
// deleteOne
// _________________________________________________________________________
db.users.deleteOne({name:'백충덕'})
// oplog
{
lsid: {
id: UUID('e573bc34-6e6c-4d27-b858-083de253605e'),
uid: Binary.createFromBase64('Y5mrDaxi8gv8RmdTsQ+1j7fmkr7JUsabhNmXAheU0fg=', 0)
},
txnNumber: Long('18'),
op: 'd',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: { name: '백충덕', age: 99, _id: ObjectId('6656da8b798ce72b3fdb83c3') },
stmtId: 0,
ts: Timestamp({ t: 1716969662, i: 96 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T08:01:02.565Z'),
prevOpTime: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') }
}
// deleteMany
// _________________________________________________________________________
db.users.deleteMany({lv:10})
// oplog (ns가 admin.$cmd 임에 주의)
{
op: 'c',
ns: 'admin.$cmd',
o: {
applyOps: [
{
op: 'd',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: {
name: '조조',
age: 10,
_id: ObjectId('6656dace798ce72b3fdb83c4')
}
},
{
op: 'd',
ns: 'service.users',
ui: UUID('a565958e-3734-4b67-8636-d670d2654900'),
o: {
name: '관우',
age: 20,
_id: ObjectId('6656dace798ce72b3fdb83c5')
}
}
]
},
ts: Timestamp({ t: 1716970514, i: 54 }),
t: Long('4'),
v: Long('2'),
wall: ISODate('2024-05-29T08:15:14.514Z')
}
'DataBase' 카테고리의 다른 글
[MongoDB] chunk/range size 변경 (0) | 2024.07.11 |
---|---|
[MongoDB] chunk 관리 (0) | 2024.07.04 |
[MongoDB] mongosh에서 JavaScript 사용하기 (0) | 2024.02.27 |
[MongoDB] mongosh editor (0) | 2024.02.20 |
[MongoDB] .mongoshrc.js (0) | 2024.02.19 |