阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MongoDB遇到疑似数据丢失的问题不要用InsertMany!

139次阅读
没有评论

共计 2984 个字符,预计需要花费 8 分钟才能阅读完成。

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

问题如下:

我通过两种方式在两个 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 推测有可能出现某些数据更新失败的情况。

更多 MongoDB 相关教程见以下内容

MongoDB 文档、集合、数据库简介  http://www.linuxidc.com/Linux/2016-12/138529.htm

MongoDB 3 分片部署及故障模拟验证  http://www.linuxidc.com/Linux/2016-12/138529.htm

Linux CentOS 6.5 yum 安装 MongoDB  http://www.linuxidc.com/Linux/2016-12/137790.htm

CentOS 7 yum 方式快速安装 MongoDB  http://www.linuxidc.com/Linux/2016-11/137679.htm

MongoDB 的查询操作  http://www.linuxidc.com/Linux/2016-10/136581.htm

在 Azure 虚拟机上快速搭建 MongoDB 集群  http://www.linuxidc.com/Linux/2017-09/146778.htm

MongoDB 复制集原理  http://www.linuxidc.com/Linux/2017-09/146670.htm

MongoDB 3.4 远程连接认证失败  http://www.linuxidc.com/Linux/2017-06/145070.htm

Ubuntu 16.04 中安装 MongoDB3.4 数据库系统  http://www.linuxidc.com/Linux/2017-07/145526.htm

MongoDB 权威指南第 2 版 PDF 完整带书签目录 下载见 http://www.linuxidc.com/Linux/2016-12/138253.htm

MongoDB 的详细介绍:请点这里
MongoDB 的下载地址:请点这里

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-12/149535.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计2984字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中