MongoDB oplog 深入剖析

MongoDB 的Replication是通过一个日志来存储写操作的,这个日志就叫做oplog。 在默认情况下,oplog分配的是5%的空闲磁盘空间。通常而言,这是一种合理的设置。可以通过mongod --oplogSize来改变oplog的日志大小。 oplog是capped collection,因为oplog的特点(不能太多把磁盘填满了,固定大小)需要,MongoDB才发明了capped collection(the oplog is actually the reason capped collections were invented). oplog的位置 oplog在local库: master/slave 架构下 local.oplog.$main; replica sets 架构下: local.oplog.rs sharding 架构下,mongos下不能查看oplog,可到每一片去看。

1mongos> use local 2switched to db local 3mongos> show collections 4Thu Mar 28 11:37:11 uncaught exception: error: { "$err" : "can't use 'local' database through mongos", "code" : 13644 }

oplog的格式 MongoDB 2.0版本

1PRIMARY> db.oplog.rs.findOne() 2{ 3 "ts" : { 4 "t" : 1354919611000, 5 "i" : 196 6 }, 7 "h" : NumberLong("-8946637877024029255"), 8 "op" : "i", 9 "ns" : "msg.msgToSend", 10 "o" : { 11 "_id" : ObjectId("50c26ecae7d64ae0b5f36cfe"), 12 ... 13 } 14}

MongoDB 2.2版本

1PRIMARY> db.oplog.rs.findOne() 2{ 3 "ts" : Timestamp(1364362801000, 8247), 4 "h" : NumberLong("8229173295225699173"), 5 "v" : 2, 6 "op" : "i", 7 "ns" : "goods.Simigoods", 8 "fromMigrate" : true, 9 "o" : { 10 "_id" : ObjectId("50b534310eba2018b88ba3b2"), 11 ... 12 } 13}

可以看到有个字段"fromMigrate" : true,之前以为是从2.0升级过来的,后查看源码发现并发如此,fromMigrate指的是chunk是迁移过来的,分片里的块移动,详见src/mongo/s/d_migrate.cpp, v表示OPLOG_VERSION,oplog版本。 新搭建的结构形如:

1PRIMARY> db.version() 22.2.2 3PRIMARY> db.oplog.rs.findOne() 4{ 5 "ts" : Timestamp(1364186197000, 58), 6 "h" : NumberLong("-7878220425718087654"), 7 "v" : 2, 8 "op" : "u", 9 "ns" : "exaitem_gmsbatchtask.jdgmsbatchtask", 10 "o2" : { 11 "_id" : "83f09a98-6a41-497b-a988-99ba5399d296" 12 }, 13 "o" : { 14 "_id" : "83f09a98-6a41-497b-a988-99ba5399d296", 15 "status" : 2, 16 "content" : "", 17 "type" : 17, 18 "business" : "832722", 19 "optype" : 2, 20 "addDate" : ISODate("2013-03-25T04:36:38.511Z"), 21 "modifyDate" : ISODate("2013-03-25T04:36:39.131Z"), 22 "source" : 5 23 } 24}

MongoDB 2.4版本

1{ 2 "ts" : { 3 "t" : 1361948104000, 4 "i" : 325 5 }, 6 "h" : NumberLong("-8795977166222676062"), 7 "v" : 2, 8 "op" : "i", 9 "ns" : "test.log", 10 "o" : { 11 "_id" : ObjectId("51031ca0c86617a8811be893"), 12 ... 13 } 14}

格式大同小异,2.4版本又改回去了。ts格式2.2版本中是Timestamp(1364186197000, 58)形式,MongoDB2.0版本及MongoDB2.4版本是{ "t" : 1361948104000, "i" : 325 }形式,另外若用MongoDB2.4版本的客户端(mongo)查看2.2版本的,看到的是MongoDB2.4版本的格式,这个只与mongo版本有关。 oplog相关字段含义 ts: the time this operation occurred. h: a unique ID for this operation. Each operation will have a different value in this field. op: the write operation that should be applied to the slave. n indicates a no-op, this is just an informational message. ns: the database and collection affected by this operation. Since this is a no-op, this field is left blank. o: the actual document representing the op. Since this is a no-op, this field is pretty useless. The o field now contains the document to insert or the criteria to update and remove. Notice that, for the update, there are two o fields (o and o2). o2 give the update criteria and o gives the modifications (equivalent to update()‘s second argument). ts:8字节的时间戳,由4字节unix timestamp + 4字节自增计数表示。 这个值很重要,在选举(如master宕机时)新primary时,会选择ts最大的那个secondary作为新primary。 op:1字节的操作类型,例如i表示insert,d表示delete。 ns:操作所在的namespace。 o:操作所对应的document,即当前操作的内容(比如更新操作时要更新的的字段和值) o2: 在执行更新操作时的条件,仅限于update时才有该属性。 其中op,可以是如下几种情形之一: "i": insert "u": update "d": delete "c": db cmd "db":声明当前数据库 (其中ns 被设置成为=>数据库名称+ '.') "n": no op,即空操作,其会定期执行以确保时效性 。 20130719更新:今天发现修改配置,会产生 "n" 操作

1{ "ts" : Timestamp(1372320938000, 1), "h" : NumberLong("2050563086860406946"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "Reconfig set", "version" : 6 } } 2{ "ts" : Timestamp(1372319914000, 1), "h" : NumberLong("5828735007195954091"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "Reconfig set", "version" : 5 } } 3{ "ts" : Timestamp(1372318223000, 1), "h" : NumberLong("512600544405470974"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "Reconfig set", "version" : 4 } }

除了以上这些,还有两个bool型的字段,一个是上面提到的fromMigrate,另一是字段b,仔细看oplog我们发现有"b":true的文档,是在delete和update操作时的bool值(update一个或多个)。 举例:

1{ 2 "ts" : { 3 "t" : 1354923335000, 4 "i" : 2 5 }, 6 "h" : NumberLong("563747339476084113"), 7 "op" : "u", 8 "ns" : "msg.device", 9 "o2" : { 10 "_id" : ObjectId("509fa1207386d978864c7833") 11 }, 12 "o" : { 13 "$set" : { 14 "flag" : "1", 15 "pin" : "5126d5b23c303", 16 "device" : "ceb27de6b9dd8f045130f046a7662630", 17 "modified" : ISODate("2012-12-07T23:36:24.628Z") 18 } 19 } 20}

了解了oplog的详细结构,我们就可以根据原理写个程序,来达到同步数据的目的,详见mongosync。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

MongoDB journal 与 oplog,究竟谁先写入?

MongoDBjournal与oplog,谁先写入?最近经常被人问到,本文主要科普一下MongoDB里oplog以及journal这两个概念。journaljournal是MongoDB存储引擎层的概念,目前MongoDB主要支持mmapv1、wiredtiger、mongorocks等存储引擎,都支持配

MongoDB 定位 oplog 必须全表扫描吗?

MongoDBoplog(类似于MySQLbinlog)记录数据库的所有修改操作,除了用于主备同步;oplog还能玩出很多花样,比如1.全量备份增量备份所有的oplog,就能实现MongoDB恢复到任意时间点的功能2.通过oplog,除了实现到备节点的同步,也可以额外再往单独的集群同步数据(甚至是异构的数据库),实现容