我怎样才能避免mongodb的竞争状况

时间:2012-05-28 04:02:33

标签: 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

    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,我怎样才能确保操作的原子? 我的recored架构是

{"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,大小,时间改变,并且shuld作为记录插入时,应该增加它。 我在{" src_md5"," src_time"," src_size"}上创建复合唯一索引,并在{" idx&#34上创建唯一索引;},但在我插入新信息之前,我应该得到idx alread存在,然后增加它。 有两种情况: 1,idx具体的md5,大小,时间,如果已经存在,只需返回idx 2,如果不存在,用1

增加idx

1 个答案:

答案 0 :(得分:1)

question中讨论了类似的问题。

你想要做的就是拥有一个独特的单调增加键,你可以将它保存在自己的集合中并使用$ inc进行增量,如链接问题所述。

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

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