添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
MongoDB 在 upsert=True 时,filter和唯一键一致,并发情况下会报错:E11000 duplicate key error collection 怎么解决?
最新推荐文章于 2023-09-18 11:40:00 发布
最新推荐文章于 2023-09-18 11:40:00 发布 阅读量 812

db.collection.createIndex({"id": 1, "platform": 1}, {unique:true})

db.collection.update_one(
    {"id": id, "platform": platform)},
    {'$set': {"some_key": data}}, upsert = True)

我已经创建了一个复合索引,并使用搜索条件将其设置为唯一,这样,在集合中,如果搜索到的内容,我搜索的内容将始终唯一。

但是在高并发的情况下,我们会有多个服务同时更新同一个collection,操作都是update_one + upsert=true 来完成的,但是每隔一段时间,服务就会报错,提示 E11000 duplicate key error collection。

这是为什么呢?
在源码中 upsert的解释是

  • upsert (optional): If True, perform an insert if no documents
    match the filter.

查询不到就插入,查询到了就更新,那会有什么问题呢? 怎么会唯一键冲突呢?
查询到官网的jira解释是:

在使用upsert=true选项进行更新期间,两个(或更多)线程可能会尝试使用相同的查询语句进行upsert操作,并且在没有找到匹配时,线程将尝试插入一个新的文档。两次插入都会(而且应该)成功,除非第二次插入导致违反唯一约束。

所以嘛,是再mongo库执行upsert的时候 并发插入导致的唯一键冲突。
官方原文链接

官方其实已经给出了解决方案,升级mongodb 到4.2 生产版本即可。

但是对于我们升级可能会有隐患的同学 就加个retry吧。

Mongodb插入数据,出现E11000 duplicate key error collection: hk-projects.administrator index: mobile_1 dup key: { mobile: null } MongoDB的默认主即_id必须在同一个集合中唯一。传统的关系型数据库通常会使用自增主,但是在分布式环境下自增是有代价的。所以MongoDB采用了另外一种主生成策略。每一个主由4部分构成: 1.unix间戳,精确到秒级别; 2.机器id; 3.进程id; 4.计数器; 前三个部分可以保证在每一秒每一个mongo进程产生的文档id是不同的。然后每一个mongo进程会自己维护一个 Error: 11000 duplicate key error collection 报错 意思是插入的id和集合中已经存在的id产生了冲突,造成这个的原因有几种,大致分类了一下,但是解决方法都大差不差,核心就是清除重复索引,手动设置id并保证id不会重复 二、报错error org.springframework.dao.DuplicateKeyException: Write failed with error code 11000 and error message 'E11000 duplicate key error collection: XXX.XXX index: _id_ dup key: { : "XXX" }'; nested exc { [MongoError: E11000 duplicate key error collection: zhihu.people index: _id_ dup key: { : ObjectId('59a3b9275f063c20cc8bdec7') }] name: 'MongoE... 在最近做的项目之中,后端数据库部分使用MongoDB。 在使用中发现了如下问题:添加第一条数据可以正常添加,第二条数据便无法添加。(无论在可视化工具中进行添加或者使用POSTMAN均无法正常添加) 将错误信息打印,如下图所示: 先说一下该条错误的中文意思:就是说该条数据的id_1这个的值为null,而第一条数据中的id_1已经为null,两条数据出现id重复,因此报错。 出现该条错误的可能原... 因为是用mongoose开发的嘛,所以我们可以去mongoose文档看看有没有有关这种错误的处理。错误信息的关信息在于,而当我是在用Validation给SchemaType做校验,而刚好文档里又说到unique不是一个校验器,那么它必然会给出处理使用unique出现的错误处理。文档给出了当出现了该如何处理,而也是受到这个启发,我就对做了处理。== - 1);});用try catch捕捉异常错误,捕捉到的错误有两种情况:一种是重复的问题,另一种是mongoose内置的校验器设置的错误。 assert: command failed: { "ok" : 0, "errmsg" : "insert for $out failed: { connectionId: 65, err: \"E11000 duplicate key error collection: admin.tmp.agg_out.6 index: _id_ dup key: { : 1 }\", code: 11... $setOnInsert指令往往同upsert、$set指令配合使用。mongodb官网说明: If an update operation with upsert: true results in an insert of a document, then $setOnInsert assigns the specified values to the fields ... 关于索引举个日常生活中的例子。拿到一本书想查阅某知识的候我们一般都会先去看目录,找到相关的章节后直接翻到对应的页码然后在这里小章节里面进一步定位我们想要的内容;这就是目录索引,能够帮助读者快读的找到想要找的内容。(一个更好的例子应该是英汉词典了,当我们查询单词的候我们不会一页一页的去遍历整个词典,而是现根据首字母快读定位到对应章节然后再根据次字母进一步缩小查询范围,知道最终找到对应单词。) 其实在数据库中也一样,索引能够极大的提高查询效率。如果没有索引mongodb在读取数据的候必须扫描集合中的每个. ObjectId介绍 在MongoDB中,文档(document)在集合(collection)中的存储需要一个唯一的_id字段作为主。这个_id默认使用ObjectId来定义,因为ObjectId定义的足够短小,并尽最大可能的保持唯一性,同能被快速的生成。 ObjectId是一个 12 Bytes 的BSON类型,其包含: 4 Bytes 自纪元间开始的秒数 目录一、MongoDB官网地址二、唯一索引(Unique Indexes)的概述三、唯一索引(Unique Indexes)的示例3.1、示例1:没有创建唯一索引,执行2次相同数据的新增操作3.2、示例2:创建唯一索引,执行2次相同数据的新增操作3.3、示例3:复合索引支持唯一性约束3.4、示例4:多索引支持唯一性约束 一、MongoDB官网地址 MongoDB官网地址:https://www.mongodb.com/docs/manual/core/index-single/ 二、唯一索引(Uniq MongoDB是一个开源的非关系型数据库。常用于作为项目的缓存数据库。因为本身提供了nodejs 可以操作的接口。所以在前端全栈工程项目中,也可以作为保存数据的仓库 本身需要进行安装使用,并且初始情况下,只能通过命令行的形式使用。不过可以使用第三方提供的可视化操作工具来间接操作MongoDB数据库-Navicat for MongoDB MongoDB数据库 - 我们可以通过MongoDB来创建一到多个非关系型数据库。每个数据库都可以包含了多个集合。每个集合可以包含多个文档。文档在程