-
Notifications
You must be signed in to change notification settings - Fork 444
oplog各字段的解析
zhangst edited this page Dec 12, 2022
·
5 revisions
本文以4.2版本里面,一条事务对应的oplog进行举例,早于4.2的版本基本跟这个差别不大,有些字段是没有的。
文章的最后会介绍kafka通道中MongoShake吐出来的oplog格式。
各字段含义如下:
- ts。操作的时间戳,64位表示,高32位是时间戳,低32位是计数累加。
- t。election term。对应raft协议里面的term,每次发生节点down掉,新节点加入,主从切换,term都会自增。
- h。操作的全局唯一id的hash结果。
- v。oplog的版本字段。
- op。具体操作类型。"i"表示插入,"d"表示删除,"u"表示更新,"c"表示是DDL操作,"n"表示是空消息(可以看作是心跳oplog)。
- ns。命名空间。操作发生在哪个表上面。
- o。具体的操作指令字段。对于op=i,这里表示插入的内容;op=d,这里表示要删除的文档;op=u,这里表示更新后的内容。
- o2。查询字段,只存在于op=u的情况,指定要操作的文档。
- ui。表的uuid。
- b。upsert。如果是true表示是以upsert的方式插入,兼容3.6以前的版本。
- wall。毫秒粒度墙上时钟。
- fromMigrate。move chunk产生的oplog。
- lsid。session id。在3.6之后,如果启动一个session并执行相应的修改操作,那么这些操作对应的oplog就会多一个这个lsid字段标识当前session。
- txnNumber。事务id。每个事务都会对应一个txnNumber。
- stmtId。
- prevOpTime。
- preImageOpTime。
- postImageOpTime。
向zz.test表插入数据{"kick":1}
:
{
"ts" : Timestamp(1582277156, 1),
"t" : NumberLong(1),
"h" : NumberLong(0),
"v" : 2,
"op" : "i",
"ns" : "zz.test",
"ui" : UUID("20d9f949-cfc7-496e-a80e-32ba633701a8"),
"wall" : ISODate("2020-02-21T09:25:56.570Z"),
"o" : {
"_id" : ObjectId("5e4fa224a6717632d6ee2e85"),
"kick" : 1
}
}
从zz.test表中移除{"kick":1}
:
{
"ts" : Timestamp(1582529794, 1),
"t" : NumberLong(1),
"h" : NumberLong(0),
"v" : 2,
"op" : "d",
"ns" : "zz.test",
"ui" : UUID("ee9b60d8-845f-42ff-989d-09018a730d60"),
"wall" : ISODate("2020-02-24T07:36:34.063Z"),
"o" : {
"_id" : ObjectId("5e537cf27dc0f30426f01b77")
}
}
普通update:db.test.update({"kick":1}, {"kick":10, "ok":true})
{
"ts" : Timestamp(1582531841, 1),
"t" : NumberLong(1),
"h" : NumberLong(0),
"v" : 2,
"op" : "u",
"ns" : "zz.test",
"ui" : UUID("ee9b60d8-845f-42ff-989d-09018a730d60"),
"o2" : {
"_id" : ObjectId("5e5384f97dc0f30426f01b79")
},
"wall" : ISODate("2020-02-24T08:10:41.636Z"),
"o" : {
"_id" : ObjectId("5e5384f97dc0f30426f01b79"),
"kick" : 10,
"ok" : true
}
}
以$set和$unset更新操作:
mgset-xxx:PRIMARY> db.test.find()
{ "_id" : ObjectId("5e5384f97dc0f30426f01b79"), "kick" : 10, "ok" : true }
mgset-xxx:PRIMARY> db.test.update({"kick":10}, {$set:{"plus_field":2}, $unset:{"ok":1}})
mgset-xxx:PRIMARY> db.test.find()
{ "_id" : ObjectId("5e5384f97dc0f30426f01b79"), "kick" : 10, "plus_field" : 2 }
{
"ts" : Timestamp(1582533077, 2),
"t" : NumberLong(1),
"h" : NumberLong(0),
"v" : 2,
"op" : "u",
"ns" : "zz.test",
"ui" : UUID("ee9b60d8-845f-42ff-989d-09018a730d60"),
"o2" : {
"_id" : ObjectId("5e5384f97dc0f30426f01b79")
},
"wall" : ISODate("2020-02-24T08:31:17.681Z"),
"o" : {
"$v" : 1,
"$unset" : {
"ok" : true
},
"$set" : {
"plus_field" : 2
}
}
}
普通replace:db.test.replaceOne({"kick" : 10}, {"kick":1, "ok":false})
{
"ts": Timestamp(1670831918,1),
"t": NumberLong(2),
"h": NumberLong(0),
"v": 2,
"op": "u",
"ns": "zz.test",
"ui": UUID("5c45ab04-8eda-49ec-998a-434c3db167a6"),
"o2": {
"_id": ObjectId("6396de5c5ee474a67d3cb436")
},
"wall": ISODate("2022-12-12T07:58:38.317Z"),
"o": {
"_id": ObjectId("6396de5c5ee474a67d3cb436"),
"kick": 1,
"ok": false
}
}
删表:mgset-xxx:PRIMARY> db.test.drop()
{
"ts" : Timestamp(1582534135, 1),
"t" : NumberLong(1),
"h" : NumberLong(0),
"v" : 2,
"op" : "c",
"ns" : "zz.$cmd",
"ui" : UUID("ee9b60d8-845f-42ff-989d-09018a730d60"),
"o2" : {
"numRecords" : 3
},
"wall" : ISODate("2020-02-24T08:48:55.148Z"),
"o" : {
"drop" : "test"
}
}
rename重命名:
mgset-22785363:PRIMARY> db.test.renameCollection("test_collection_rename")
{
"ts" : Timestamp(1582534922, 1),
"t" : NumberLong(1),
"h" : NumberLong(0),
"v" : 2,
"op" : "c",
"ns" : "zz.$cmd",
"ui" : UUID("da21cb04-a4c8-46ad-8b3c-3e8e9314f4b5"),
"wall" : ISODate("2020-02-24T09:02:02.685Z"),
"o" : {
"renameCollection" : "zz.test",
"to" : "zz.test_collection_rename",
"stayTemp" : false
"dropTarget": UUID("52c1c147-2408-4d96-9d0f-889a759ab079"), // field only exists when target collection is exists
}
}
删库:mgset-22785363:PRIMARY> db.dropDatabase()
{
"ts" : Timestamp(1582535589, 4),
"t" : NumberLong(1),
"h" : NumberLong(0),
"v" : 2,
"op" : "c",
"ns" : "zz.$cmd",
"wall" : ISODate("2020-02-24T09:13:09.165Z"),
"o" : {
"dropDatabase" : 1
}
}
一个事务DDL:
{
"ts" : Timestamp(1530696933, 1),
"t" : NumberLong(1),
"h" : NumberLong("4217817601701821530"),
"v" : 2,
"op" : "c",
"ns" : "admin.$cmd",
"wall" : ISODate("2018-07-04T09:35:33.549Z"),
"lsid" : {
"id" : UUID("e675c046-d70b-44c2-ad8d-3f34f2019a7e"),
"uid" : BinData(0, "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=")
},
"txnNumber" : NumberLong(0),
"stmtId" : 0,
"prevOpTime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"o" : {
"applyOps" : [
{
"op" : "i",
"ns" : "test.coll2",
"ui" : UUID("a49ccd80-6cfc-4896-9740-c5bff41e7cce"),
"o" : {
"_id" : ObjectId("5b3c94d4624d615ede6097ae"),
"x" : 20000
}
},
{
"op" : "i",
"ns" : "test.coll3",
"ui" : UUID("31d7ae62-fe78-44f5-ba06-595ae3b871fc"),
"o" : {
"_id" : ObjectId("5b3c94d9624d615ede6097af"),
"x" : 20000
}
}
]
}
}
MongoShake的json格式吐出的oplog基本跟原生的oplog格式一样,但是多了几个用于标记的字段:UniqueIndexesUpdates
, RawSize
, SourceId
,这几个字段用户不需要关心,将会在2.4版本去除,g
和uk
是阿里云针对内核修改支持的字段,开源用户也不需要关心。
下面以2个用户吐出的Oplog为例挨个解释每个field的意义和格式:
{
"ts": 6799808956219785217, // 64位时间戳,其格式就是类似"Timestamp(1582277156, 1)",右移32位可以得到32位的秒级时间戳
"op": "i", // 插入操作
"g": "", // 阿里云内核独有,开源版本请忽略
"ns": "dict.test", // 针对db=dict,collection=test的操作
"o": [{ // 具体插入的文档内容,Name表示key,Value表示value,翻译过来下面这个就是:o:{"_id": "5e5dc63842d2a398850d6222", "name": "zhangsan", "age": 18}
"Name": "_id",
"Value": "5e5dc63842d2a398850d6222"
}, {
"Name": "name",
"Value": "zhangsan"
}, {
"Name": "age",
"Value": 18
}],
"o2": null, // o2字段
"uk": null, // 阿里云内核独有,开源版本请忽略
"lsid": null, // session字段
"fromMigrate": false, // move chunk字段
"UniqueIndexesUpdates": null, // MongoShake标记字段,2.4以前版本请忽略
"RawSize": 131, // MongoShake标记字段,2.4以前版本请忽略
"SourceId": 0 // MongoShake标记字段,2.4以前版本请忽略
}
{
"ts": 6799816725815623681, // 同上个示例,时间戳
"op": "u", // update操作
"g": "", // 同上个示例,忽略
"ns": "dict.test", // 同上个示例, namespace
"o": [{ // 相当于o:{$set:{"content": "来个中文咋样---"}}
"Name": "$set",
"Value": [{
"Name": "content",
"Value": "来个中文咋样---"
}]
}],
"o2": { // query字段,相当于: o2:{"_id": "5e5dcb5942d2a398850d6224"}
"_id": "5e5dcb5942d2a398850d6224"
},
"uk": null, // 同上个示例,忽略
"lsid": null, // 同上个示例
"fromMigrate": false, // 同上个示例
"UniqueIndexesUpdates": null, // 同上个示例,忽略
"RawSize": 154, // 同上个示例,忽略
"SourceId": 0 // 同上个示例,忽略
}
需要注意的是,o
字段的格式与其他字段不同,o
字段是bson.D的结构(数组嵌套字段),o2
是bson.M结构(字典)
oplog_entry.idl