MongoDB原子性问题 - 修改内存中的文档

时间:2012-03-06 16:53:58

标签: python mongodb atomicity

我正在使用MongoDB处理当前项目,并对构建对并发修改的支持的正确方法感到困惑。

我有一个对象数组。当请求进来时,我想检查该数组中的最后一个元素,并就如何响应做出条件决定。我的代码如下所示:

# Find the last object ID in the array.
last_element_id = str(document['objects'][-1])
if last_element_id != the_element_id_the_request_is_responding_to:
    db.documents.insert({
        ...
    })
else:
    # Append the response to the end of the array.
    document['objects'].append(new_element_id)
    db.documents.save(document)

我很关注以下情况:

  1. 在处理请求A时,我发现last_element_id有效,并且 响应应附加到列表的末尾。
  2. 之前 append()和save()操作完成,另一个请求B是 处理。
  3. B也看到last_element_id有效,追加() 响应和保存()。
  4. 现在,A的回应排在最后 数组,但响应不再遵循假设 'last_element_id',因为B的回应事先偷偷摸摸。
  5. 在Mongo的原子模型中处理这种逻辑的正确方法是什么?如果可以避免使用锁,我不想使用锁,因为WSGI应用程序可以同时在多个进程中运行。

    谢谢!

2 个答案:

答案 0 :(得分:1)

你可以使用乐观锁定.. ,,一种方法是在文档中添加一个名为version的字段,然后在每次更新时增加它,并在更新时确保文档中的版本与文档中的版本相同你读完了。

我可以提供更多详细信息,但在http://www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-%22UpdateifCurrent%22

中有相当详细的记录

让我知道这是否适合您,

答案 1 :(得分:1)

您可以使用findAndModify来atomicallay处理事务(至少在这种情况下)。

此命令接受upsert标记,您可以使用该标记根据文档existence更新或插入文档。请查看以下示例

> db.upsertTest.find()
{ "_id" : 1, "arr" : [ 1 ] }

并使用查询_id:1发出此命令会将新项目推送(追加)到arr

> db.upsertTest.findAndModify({query: {_id:1},update:{$push:{arr:2}},upsert:true,"new":true})
{ "_id" : 1, "arr" : [ 1, 2 ] }

这将创建一个新的,因为_id:2已不存在

> db.upsertTest.findAndModify({query: {_id:2},update:{$push:{arr:2}},upsert:true,"new":true})
{ "_id" : 2, "arr" : [ 2 ] }

> db.upsertTest.find()
{ "_id" : 1, "arr" : [ 1, 2 ] }
{ "_id" : 2, "arr" : [ 2 ] }

希望它有所帮助。