mongodb中出现_id字段重复记录的排查笔记
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了mongodb中出现_id字段重复记录的排查笔记,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6868字,纯文字阅读大概需要10分钟。
内容图文
近期在使用mongodb的过程中遇到一次表中有几百条_id字段重复的记录(相同_id的有两条),着实吓了一大跳,因为_id字段在mongodb里面已经默认创建了唯一索引,理论上是不可能有重复记录的,因此特把排查过程记录下来。
1. 问题定位
发现这个现象,是在定位一个问题的时候,发现了这批重复脏数据,bug出现的步骤:把一条记录中的某个字段修改后,再执行save方法,由于修改的字段是shard key,且保存的时候路由到另外一组shard(和原记录的shard不同),导致了重复_id的出现。
2. 问题复现
首先,准备测试元数据,插入脚本如下:
db.auth("test","test"); var total = 500; var page = 1000; for(i=1; i<=total; i++){ for(var j 0= 1; j <= page; j++){ db.users.save({‘_id‘: ‘user‘+i+"-"+j,‘age‘:j,"content":"012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901223456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567823456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"}); } }
其中content字段的内容很长,1000个字符,这样50w条元数据的数据量是满足分片后的数据迁移条件的(数据量太小,mongodb是不会迁移的)。
把该文件保存在mongo可执行程序的目录,再执行数据插入:
/mongo 127.0.0.1:30000/test saveUser.js
随后对test集合创建索引,并进行分片:
db.users.createIndex({"age":1})
sh.enableSharding("test") sh.shardCollection("test.user", { age: 1 } )
等待分片数据迁移结束后,查看分片状态:
sh.status()
user表的分片数据如下:
{ "_id" : "test", "primary" : "repa", "partitioned" : true } test.user shard key: { "age" : 1 } unique: false balancing: true chunks: repa 14 repb 11 too many chunks to print, use verbose if you want to force print
基础数据已经准备完毕了,下面开始造数据,首先查询到第一条记录内容如下:
{ "_id" : "user1-1", "age" : 1.0, "content" : "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901223456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567823456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" }
然后把该记录的内容拷贝一份,并把age修改为1000,然后再保存到users集合中:
MongoDB Enterprise mongos> db.users.save({ "_id" : "user1-1", "age" : 1000.0, "content" : "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901223456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567823456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" })
此时_id为“user1-1”的记录已经有两条了:
MongoDB Enterprise mongos> db.users.find({"_id":"user1-1"}) { "_id" : "user1-1", "age" : 1000, "content" : "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901223456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567823456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" } { "_id" : "user1-1", "age" : 1, "content" : "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901223456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567823456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" }
3. 避免措施
从以上分析可知,在对分片集合进行修改操作或者新写入操作时,要特别注意,由于shard key的路由问题,可能会导致_id字段或者其他唯一字段重复记录(保存在不同的shard中),为了避免重复记录,选择shard key时,可以把唯一字段也加入到shard key中,以本次测试为例,shard key可以设置为{"age":1, "_id":1},如果不想把_id加入到shard key中,且业务上面不允许_id重复,则需要在写入前先执行查询。
原文:https://www.cnblogs.com/xinghebuluo/p/12623311.html
内容总结
以上是互联网集市为您收集整理的mongodb中出现_id字段重复记录的排查笔记全部内容,希望文章能够帮你解决mongodb中出现_id字段重复记录的排查笔记所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。