-2

我想更新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 已经存在,然后增加它。有两种情况: 1,idx与特定的md5,大小,时间,如果已经存在,则返回idx 2,如果不存在,将idx增加1

4

1 回答 1

2

在这个问题中讨论了一个类似的问题。

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

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

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

于 2012-05-28T17:23:19.110 回答