多进程Upsert重复键错误(Mongo> = 3.0.4 WiredTiger)

mem*_*box 10 mongodb

所有

我刚从我们的applcation发出了一个奇怪的错误:

当我用两个进程更新时,它抱怨一个具有唯一索引的集合上的重复键错误,但是有问题的操作是一个upsert.

案例代码:

import time
from bson import Binary
from pymongo import MongoClient, DESCENDING

bucket = MongoClient('127.0.0.1', 27017)['test']['foo']
bucket.drop()
bucket.update({'timestamp': 0}, {'$addToSet': {'_exists_caps': 'cap15'}}, upsert=True, safe=True, w=1, wtimeout=10)
bucket.create_index([('timestamp', DESCENDING)], unique=True)
while True:
    timestamp =  str(int(1000000 * time.time()))
    bucket.update({'timestamp': timestamp}, {'$addToSet': {'_exists_foos': 'fooxxxxx'}}, upsert=True, safe=True, w=1, wtimeout=10)
Run Code Online (Sandbox Code Playgroud)

当我用两个进程运行脚本时,Pymongo Exception:

Traceback (most recent call last):
  File "test_mongo_update.py", line 11, in <module>
    bucket.update({'timestamp': timestamp}, {'$addToSet': {'_exists_foos': 'fooxxxxx'}}, upsert=True, safe=True, w=1, wtimeout=10)
  File "build/bdist.linux-x86_64/egg/pymongo/collection.py", line 552, in update
  File "build/bdist.linux-x86_64/egg/pymongo/helpers.py", line 202, in _check_write_command_response
pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: test.foo index: timestamp_-1 dup key: { : "1439374020348044" }
Run Code Online (Sandbox Code Playgroud)

ENV:

  • mongodb 3.0.5,WiredTiger

  • 单个mongodb实例

  • pymongo 2.8.1

mongo.conf

systemLog:
   destination: file
   logAppend: true
   logRotate: reopen
   path: /opt/lib/log/mongod.log

# Where and how to store data.
storage:
   dbPath: /opt/lib/mongo
   journal:
     enabled: true

   engine: "wiredTiger"
   directoryPerDB: true

# how the process runs
processManagement:
   fork: true  # fork and run in background
   pidFilePath: /opt/lib/mongo/mongod.pid

# network interfaces
net:
   port: 27017
   bindIp: 0.0.0.0  # Listen to local interface only, comment to listen on all interfaces.

setParameter:
   enableLocalhostAuthBypass: false
Run Code Online (Sandbox Code Playgroud)

关于这里可能出现什么问题的任何想法?

PS:

我在MMAPV1存储引擎中重试了同样的情况,它运行正常,为什么?

我在这里找到了相关的东西:https: //jira.mongodb.org/browse/SERVER-18213

但是在这个bug修复之后,它会出现这个错误,所以看起来这个bug并没有完全修复.

干杯

mem*_*box 7

我发现了这个错误:https: //jira.mongodb.org/browse/SERVER-14322

请随时投票支持并观看更多更新.


Mat*_*att 6

upsert既检查要更新的现有文档,也插入新文档.

我最好的猜测是你遇到了一个时间问题:

  1. 过程2检查是否存在,而不是
  2. 过程1检查是否存在,而不是
  3. 过程2插入,有效
  4. 过程1插入,提升了重写键.

首先检查你的python库首先发送的本机查询.确认它是你对原生mongo方面的期望.然后,如果您可以定期在有线电视上重播此半音,但从不在mmap上重播,请使用mongo引发错误,以确认其预期行为是什么.有时很难选择他们保证原子的东西.

这是为什么Mongo ObjectID将时间戳,机器ID,pid和计数器组合为唯一性的一个很好的例子.