java mongodb 丢数据_MongoDB遇到的疑似数据丢失的问题。不要用InsertMany!

最近做数据备份的时候发现了有个很严重的问题,那就是数据丢失(最后证明没丢,是别的问题造成的)。

问题如下:

我通过两种方式在两个mongoDB集群中,对一组collection进行备份,最后2个备份数据的数据个数不相同,并且都小于原始collection的count结果。于是便开始寻求解决办法,流程如下:

1、记录3组数据,原始数据集按条件count有909217个数据,备份代码如下,其中replaceOne备份下来的数据有907582条,而使用insertMany备份下来的结果有906281条(注释是之后加的,之前用的是insertMany):

rdd.foreachPartition { x => {

val mongoURI = new MongoClientURI(uri)

val mongo = new MongoClient(mongoURI)

val db = mongo.getDatabase("wenshu")

val dbColl = db.getCollection("testbackup")

val mongoURI2 = new MongoClientURI(uri2)

val mongo2 = new MongoClient(mongoURI2)

val db2 = mongo2.getDatabase("wenshu")

val dbColl2 = db2.getCollection(backName)

var count = 0

var resList = new ArrayList[Document]

x.foreach(y => {

//count = count + 1

//resList add y

try{

dbColl.replaceOne(eqq("_id", y.get("_id")), y, new UpdateOptions().upsert(true))

dbColl2.insertOne(y)

}catch{

case e: Throwable => e.printStackTrace()

}

//使用这种方式插入会导致插入的数据和真实数据数量对应不上, 先注释掉有机会再找原因

//if (count == 10000){

//try{

//dbColl2.insertMany(resList, new InsertManyOptions().ordered(false))

//}catch{

//case e: Throwable => e.printStackTrace()

//}

//resList.clear

//count = 0

//}

})

//if (count > 0)

//try{

//dbColl2.insertMany(resList, new InsertManyOptions().ordered(false))

//}catch{

//case e: Throwable => e.printStackTrace()

//}

2、通过查询stackoverflow和jira发现数据丢失问题曾经存在过,但都是2.0之前的mongodb,现在商用化之后的mongodb基本没人出现过数据丢失问题。

3、检查代码,发现不是插入代码错误。

4、对抽出来的907582条数据的库进行备份,还是用上述程序,发现replaceOne的数据有907582,而insertmany只有904291条数据。

5、结合上述条件,推测是insertMany导致部分数据丢失,所以才会出现insertMany结果和replaceOne不一样。

6、对此结论进行测试,将insertMany改为上述代码中的insertOne重新备份907582条数据。

7、结果正确,重新备份下来的2份数据都是907582条。目前解决了其中一个问题,就是备份出来的两份数据不一样多的问题,接下来考虑备份数据和从总库中抽取的数据不一致的问题。

8、对mongo shell的count操作查找其工作原理,发现有一些报告count数据不准的问题,结合自身原因推测是count的问题,数据应该只有907582条。

9、通过多抽取几遍对这个问题进行测试,按同样条件抽了3遍返回的结果都是907582条,可以认定数据库中只有907582条满足此条件的数据。

结论:

1、MongoDB的Count操作有可能返回错误的结果。至少在Sharding Cluster,多个索引和2级索引的条件下会出现这种问题。

2、插入时不要使用InsertMany,会导致数据丢失。

3、同理,尽量不要使用updateMany,虽然不会导致数据丢失,但是按照结论2推测有可能出现某些数据更新失败的情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值