如何避免mongodb竞争条件

如何避免mongodb竞争条件,mongodb,atomic,race-condition,Mongodb,Atomic,Race Condition,我想更新mongodb中的一些数据,我的逻辑如下: #find the specific document with "md5,time,size", if collection.find({"src_md5":file_md5,"src_time":file_time,"src_size":file_size}).count() == 0: #if not found # find the idx,if idx is not yet exist,set idx equa 1

我想更新mongodb中的一些数据,我的逻辑如下:

#find the specific document with "md5,time,size",
if collection.find({"src_md5":file_md5,"src_time":file_time,"src_size":file_size}).count() == 0:
    #if not found
    #   find the idx,if idx is not yet exist,set idx equa 1

    if collection.find({},{"idx":1}).count() == 0:
        idx = 1

    #if idx is alread there, sort idx and get the biggest idx
    else:
        idx = collection.find({},{"idx":1}).sort('idx',-1).limit(5)[0]['idx']
        idx = idx + 1

        #insert the info with idx
        if not self.insertFileInfo(collection,file_obj,file_md5,file_time,file_size,long(idx)):
            return None
#if the specific document with "md5,time,size" is found
else:
#just get the idx with the specific md5
    idx = collection.find({"src_md5":file_md5,"src_time":file_time,"src_size":file_size},{"idx":1})[0]['idx']
    return None
我将在4台机器上运行上述代码,这意味着4个进程将几乎同时更新mongodb,如何确保操作的原子性? 我的记录模式是

{"src_md5":"djapijfdakfiwqjfkasdj","src_size":2376498,"src_time":1338179291,"idx":1}
{"src_md5":"jdfipajkoijjipjefjidwpj","src_size":234876323,"src_time":1338123873,"idx":2}
{"src_md5":"djapojfkdasxkjipkjkf","src_size":3829874,"src_time":1338127634,"idx":3}
它不是一个简单的自动递增键,它应该在md5、大小、时间改变时增加,并且应该作为记录插入。 我在{“src_md5”、“src_time”、“src_size”}上创建了一个复合唯一索引,并在{“idx”}上创建了一个唯一索引,但在插入新信息之前,我应该先获取idx alread exist,然后增加它。 有两种情况: 1、具有特定md5、大小、时间的idx,如果已经存在,只需返回idx即可
2,如果不存在,则用1增加idx。本节将讨论类似的问题

您想要做的类似于拥有一个唯一的单调递增键,您可以将其保存在自己的集合中,并使用$inc进行递增,如链接问题中所述

这将确保您永远不会尝试使用相同的idx两次。现在仍然有可能两个线程将尝试使用两个不同的idx键插入(md5,size,time)的新组合,但第二个将失败,因为您在(md5,size,time)上有唯一的索引


这里唯一存在的竞争条件是,当第二个线程由于唯一索引而无法插入时,您将得到一个未使用的idx值(即,每次发生这种情况时,增加idx值将跳过一个)。这对你来说有多大问题?如果是大的,您必须在应用程序代码中强制锁定,或者您可以更改模式的结构来处理这种情况。

看起来您的代码在所有路径上都没有返回任何值。这是打字错误吗?这四个字段是文档中唯一的字段吗?这些文件的属性是否具有其他属性(如文件名或类似属性?)