确保MongoDb';找到了吗?

确保MongoDb';找到了吗?,mongodb,pymongo,Mongodb,Pymongo,我有一个MongoDB集合(用作作业队列),多个进程使用find和modify从中读取记录FindAndModify搜索active字段为“false”的记录,将其设置为“true”,以便其他进程不读取相同的记录 问题是查看日志时,我发现不同的进程仍然读取相同的记录。当两个进程同时从队列中读取时,似乎会发生这种情况。有没有办法确保一次只能有一个进程读取集合 我使用的是Mongo 2.2.3和pymongo 2.2 非常感谢 编辑:相关日志包括: 工人3 2013-03-18 23:57:4543

我有一个MongoDB集合(用作作业队列),多个进程使用
find和modify
从中读取记录
FindAndModify
搜索
active
字段为“false”的记录,将其设置为“true”,以便其他进程不读取相同的记录

问题是查看日志时,我发现不同的进程仍然读取相同的记录。当两个进程同时从队列中读取时,似乎会发生这种情况。有没有办法确保一次只能有一个进程读取集合

我使用的是Mongo 2.2.3和pymongo 2.2

非常感谢

编辑:相关日志包括:

工人3 2013-03-18 23:57:45434默认工人3
项目名称信息队列作业:作业id:5147a90f68e8fe0097002bdf

工人3 2013-03-18 23:57:47608默认工人3
项目名称信息输入:14497个文档

工人2 2013-03-18 23:57:45440默认工人2
项目名称信息队列作业:作业id:5147a90f68e8fe0097002bdf

工人2 2013-03-18 23:57:47658默认工人2
项目名称信息输入:14497个文档

如您所见,worker.3和worker.2从队列中读取相同的作业(这两个worker具有相同的mongodb id)

查找和修改命令:

query = {"active": False}
try:
    return self.collection.find_and_modify(
            query=query,
            update={"$set": {"active": True}},
            upsert=False,
            sort={"added_on": 1},
            limit=1
        )
except Exception, exc:
    LOGGER.exception(exc)

将“锁定”分为两个阶段。第一个更新记录查询第一个没有锁时间戳或时间戳已过期的对象并设置新锁。然后使用刚刚建立的锁数据查找相同的对象。

首先对mongodb进行简单的查询,以获得单个作业记录

job = db.coll.find({query}).limit(1)
接下来更新指定作业id的记录,其中
active=false

update_response = db.coll.update(
    {_id:job.id, active=false},
    {$set:{active:true}},
    false,
    false
)
如果作业已由另一个进程更新,则由于查询约束
active=false
,更新将不会成功。在更新\u响应中检查记录是否已更新:

if update_response['n'] > 0 and update_response['updatedExisting']==true:
    return job

如果您的更新未成功,请获取另一个作业并重试。

让我说清楚一点-在您的场景中,两个不同的findAndModify命令不可能返回相同的文档

不可能。以下是执行工作的方法的前几行:

    Lock::DBWrite lk( ns );
    Client::Context cx( ns );

    BSONObj doc;

    bool found = Helpers::findOne( ns.c_str() , queryOriginal , doc );
注意第122行,其中在查找之前获取了写锁

两个进程不可能同时持有写锁。似乎更有可能发生了一些不同的事情(多个文档具有相同的id值,调用find_和_modify的函数返回相同的文档,并将其返回到两个线程,还有一些我们不太了解的事情)


FindAndModify是一个原子命令,在执行期间持有独占写锁。我的建议是深入了解日志真正向您展示的内容,而不是基于对必须发生的事情的不正确/无根据的假设对代码进行更改。

您可以发布您正在进行的实际
findAndModify
通话吗?result=self.collection.find\u和\u modify(query=query,update={“$set”:{“active”:True}},upsert=False,sort={“added_on”:1},limit=1)是否
查询
包括
{“活动”:False}
?是的,它确实包括它。您可以尝试:将
活动
布尔值更改为
数字
;在
活动
字段
更新:{$inc:{active:1}上使用
$inc
;并修改您的查询以指定
active
的值必须等于
0
find和modify
应该是原子的。因此,在测试之后,您是否看到
active>0
的值?如果每个进程完成的工作都非常快,这是否会导致大量的争用寻找未完成的作业文档删除?(
查找
,然后尝试
更新
,失败,
查找
,尝试…)这似乎是不必要的-FindDandModify为您处理此问题。我认为OP没有准确解释日志。我不认为这与搜索
active:false
的原子
FindDandModify
有何不同。我同意@wiredPairie-FindDandModify只是将更新和返回文档合并为一个步骤。