【问题标题】:MongoDB race condition on insert during load test负载测试期间插入时的 MongoDB 竞争条件
【发布时间】:2014-11-12 13:04:40
【问题描述】:

在执行负载测试时,我有时会遇到以下情况:这段代码(简化):

var person = Persons.findOne();
if(person == null){
         Persons.insert(newDocument);
}

抛出一个错误,因为插入操作与现有文档冲突——即使我刚刚使用 findOne() 检查了它。 Mongo shell 在 insert() 之前暂停时显示文档。

错误是:

WriteConcern detected an error ''. (Response was { "ok" : 1, "code" : 11000, "err" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: MainDB.Persons.$Person UniquePersonID dup key: { : \"BOT 878611 141152\" }", "n" : NumberLong(0) }).

唯一索引是:

{ v: 1, name: "Person UniquePersonID", key: { UniquePersonID : 1 }, unique: true, ns: "MainDB.Persons", sparse: true, dropDups: true, background: true }

这听起来像是一种竞争条件,我正在尝试找到解决此问题的正确方法:

  1. 使用 $setOnInsert
  2. 将 findAndModify 与 Upsert 标志一起使用
  3. 将 Update 与 Replace 和 Upsert 结合使用

这些方法的问题是1+2只替换某些字段,我想替换整个文档,方法3替换整个文档但是_id冲突。

(如果相关,我使用的是官方 C# 驱动程序版本 1.9.2.235)

感谢您的帮助。

【问题讨论】:

  • 您能否明确您收到的错误以及您最终要使用该代码完成什么?文档示例也有帮助。看起来您应该尝试在不检查的情况下插入文档,就好像文档存在一样,您会在 _id 上获得唯一的密钥违规,但根据您提供的信息很难判断。
  • @wdberkeley - 添加了更多详细信息,谢谢。

标签: c# mongodb mongodb-.net-driver


【解决方案1】:

好的,如果我理解正确的话,您需要执行以下操作:

  1. 检查具有给定 UniquePersonId 的文档是否存在
  2. 如果没有,请插入具有该 UniquePersonId 的文档
  3. 如果确实存在这样的文档,则什么也不做。

您的代码遇到了重复键错误,原因与您认为的相同 - 另一个线程在 findOneinsert 之间插入了相同的 UniquePersonId。没关系 - 错误只是告诉代码一些其他进程已经完成了它的工作。唯一索引违规错误并不是某种错误意义上的错误,即某些东西无法正常工作。它只是让您知道您的操作由于您施加的唯一约束而无效。我认为(不了解更多有关此上下文的内容)您可以运行插入并在发生唯一索引错误时吞下它。

【讨论】:

  • 所以它可以是这样的:tr​​y{Insert();}catch{} 来实现这一点。但是你的意思是没有更好的方法来解决这个问题?
  • 您希望有什么更好的方式存在?对我来说似乎很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-21
  • 1970-01-01
  • 2017-02-20
  • 2013-03-30
相关资源
最近更新 更多