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推測有可能出現某些數據更新失敗的情況。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM