zoukankan      html  css  js  c++  java
  • 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推测有可能出现某些数据更新失败的情况。

  • 相关阅读:
    QR code 乱谈(一)
    用JAVA实现数字水印(可见)
    ctf总结
    Unix/Linux常用命令
    C语言概述
    C语言发发展历史
    为什么要学习C语言
    计算机应用领域
    计算机发展趋势
    如何学习计算机
  • 原文地址:https://www.cnblogs.com/gaoze/p/7735210.html
Copyright © 2011-2022 走看看