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推测有可能出现某些数据更新失败的情况。
MongoDB遇到的疑似数据丢失的问题。不要用InsertMany!的更多相关文章
- SQL Server AlwaysON 同步模式的疑似陷阱
原文:SQL Server AlwaysON 同步模式的疑似陷阱 SQL Server 2012 推出的最重要的功能之一Alwayson,是一个集之前Cluster和Mirror于一体的新功能,即解决 ...
- 疑似CPU或者内存故障导致进程崩溃
我们有一个服务跑在微软云的所有宿主机上.最近发现某一台机器上该服务进程持续崩溃.崩溃原因是访问了一个无效指针,对应的代码如下 serviceListIniBuffer.AppendF("Se ...
- 2018-12-09 疑似bug_中文代码示例之Programming in Scala笔记第九十章
续前文: 中文代码示例之Programming in Scala笔记第七八章 源文档库: program-in-chinese/Programming_in_Scala_study_notes_zh ...
- 2.5星|《AI进化论》:疑似基于PPT与公关稿整理汇编而成
AI进化论·解码人工智能商业场景与案例 全书是目前AI在一些热门领域的应用的介绍,包括各行业内AI可以实现的功能.现有相关公司的具体业务等.对各公司的介绍仅限于能实现什么业务,具体做的怎么样,有什么优 ...
- 如何看待B站疑似源码泄漏的问题?
今天突然看到关于B站源码泄漏事.网曝B站整个网站后台工程源码遭泄露,开源项目平台Github上疑似出现了Bilibili网站后台工程,内含部分用户名密码.目前官方还没对此事作出任何回应,所以还无法确定 ...
- 计蒜客 疑似病毒 (AC自动机 + 可达矩阵)
链接 : Here! 背景 : 开始我同学是用 AC自动机 + DP 的方法来做这道题, 这道题的标签是 AC自动机, 动态规划, 矩阵, 按道理来说 AC自动机 + DP 应该是能过的, 但是他不幸 ...
- [转帖]疑似兆芯开先KX-7000跑分曝光:IPC性能大幅提升
疑似兆芯开先KX-7000跑分曝光:IPC性能大幅提升 https://www.bilibili.com/read/cv4028300 数码 11-23 1589阅读28点赞22评论 尽管有ARM架构 ...
- [转帖]WannaCry惊天大发现!疑似朝鲜黑客组织Lazarus所为
WannaCry惊天大发现!疑似朝鲜黑客组织Lazarus所为 Threatbook2017-05-16共588524人围观 ,发现 17 个不明物体系统安全 https://www.freebuf. ...
- MySQL 对window函数执行sum函数疑似Bug
MySQL 对window函数执行sum函数疑似Bug 使用MySql的窗口函数统计数据时,发现一个小的问题,与大家一起探讨下. 环境配置: mysql-installer-community-8.0 ...
随机推荐
- 三、Spring Boot 日志
1.日志框架 小张:开发一个大型系统: 1.System.out.println(""):将关键数据打印在控制台:去掉?写在一个文件? 2.框架来记录系统的一些运行时信息:日志框架 ...
- centos安装Django之三:安装python
这是centos安装Django系列第三篇,安装python.centos系统已经自带了python2.6,但是它被系统很多程序所依赖,不建议删除.我们可以使用以下命令来查看我们使用的Python版本 ...
- zabbix基础知识
zabbix监控 初级 1.识别监控对象(分级) 2.理解监控对象(理论知识) 3.细分监控对象的指标 4.确定报警的基准线 预中级 1.工具化和监控分离 2.监控对象的分类 2.1硬件监控(方法:机 ...
- 同一局域网运行两套LVS
两套LVS的ID必须不一致 ,原文: http://blog.chinaunix.net/uid-29578485-id-5671910.html 在LVS服务器中修改配置文件 vi /etc/ke ...
- pt-table-checksum 使用实践
在另外部署的机器上执行: pt-table-checksum h='192.168.122.47',u='root',p='cc.123',P=3306 -d cat --nocheck-r ...
- 【剑指offer】两个链表的第一个公共结点
一.题目: 输入两个链表,找出它们的第一个公共结点. 二.思路: 思路一:模拟数组,进行两次遍历,时间复杂度O(n2) 思路二:假定 List1长度: a+n List2 长度:b+n, 且 a&l ...
- Redis入门到高可用(三)——通用命令
通用命令 参考 http://redisdoc.com/index.html 1. keys #查看所有key 时间复杂度:O(N), N 为数据库中 key 的数量. 127.0.0.1:637 ...
- System.getProperty("user.dir")
/**获得当前类的完整路径.最后一句*/package test;import java.net.MalformedURLException;import java.net.URI;import ja ...
- golang gui library 库
andlabs/ui已经重写,稳定性增强,但是组件很少,只提供了几种基础的控件,慎用.gxui死了,别用.linuxdeepin转QT了,所以…… windows系统最好的选择是walk. 首先,写w ...
- 如何创建线程第一种继承Thread类
步骤 1:定义一个类 继承Thread类.2:重写Thread类的run方法.3:直接创建Thread的子类对象创建线程.4:调用start方法开启线程并调用线程的任务run方法执行.-------- ...