目录

MongoDB文档数据顺序

目录

直接从问题出发,数据备份与恢复相关的。

备份,从源数据库导出全量数据(mongodump),备份oplog; 恢复,向目标数据库导入全量数据(mongorestore),重放oplog。

正常来讲,源端和目标端数据库最终数据一致,可以通过dbHash命令校验,但实际情况是dbHash校验结果不一致

排查发现,时间点固定,多次执行数据恢复(删除数据-全量导入-重放oplog),每次目标数据库的dbHash结果都不一样,可以确定问题出在重放oplog这里。

既然重放过程中程序并没有异常,说明数据成功写入,原因只应该是数据的二进制存储内容不一致。

程序用Go写的,mongo驱动是mgo,oplog读出来后用Bson.M暂存,然后将其Marshal并写入文件,Bson.M的API文档描述如下:

type M map[string]interface{}

M is a convenient alias for a map[string]interface{} map, useful for dealing with BSON in a native way. For instance:

bson.M{"a": 1, "b": true}

There’s no special handling for this type in addition to what’s done anyway for an equivalent map type. Elements in the map will be dumped in an undefined ordered. See also the bson.D type for an ordered alternative.

再看看Bson.D

type D []DocElem

D represents a BSON document containing ordered elements. For example:

bson.D{ {"a", 1}, {"b", true} }

In some situations, such as when creating indexes for MongoDB, the order in which the elements are defined is important. If the order is not important, using a map is generally more comfortable. See bson.M and bson.RawD.

这里解释下BSON,Binary JSON的缩写,JSON的二进制序列,MongoDB底层采用的数据存储格式。

Bson.M是map类型,内部元素在导出时顺序是不确定的,比如说{a: 1, b: 2},可能先导出a,也可能先导出b,两份bson数据逻辑上相同,二进制存储内容不同,所以md5算出来的结果也不同;

Bson.D是array类型,元素有序,反序列化过程逐步追加到数组末尾,而且提到有些情况下数据顺序很关键,比如建索引,在我之前的一个文章里也提到。

好,这里增加一个情况,基于oplog重放的数据恢复与校验