如何将 pymongo 收藏锁定为阅读和写作?



我有一个运行在docker容器上的mongo实例:

docker run 
-d 
--name mongo 
-e MONGO_INITDB_ROOT_USERNAME=bla 
-e MONGO_INITDB_ROOT_PASSWORD=bla 
-p 27017:27017 
mongo

和我有一个进程使用mongo如下方式:

def init():
client = pymongo.MongoClient('mongodb://bla:bla@localhost:27017')
db = client['db']
collection = db['col']
collection.insert_one({'ok': False})
return collection

def critical_section(collection):
if list(collection.find({'ok': False})):
# do stuff
collection.update_one({'ok': False}, {'ok': True})

collection = init()
critical_section(collection)

我有许多并发进程运行critical_section函数,所以我想在临界区之前锁定集合,然后解锁它(如果我不这样做,2个进程可以find一个文档,但是,第一个将设法更新,第二个将失败…)

我用这个答案来锁定db:

collection = init()
pymongo.MongoClient('mongodb://bla:bla@localhost:27017')['admin'].command('fsync', lock=True)
critical_section(collection)
pymongo.MongoClient('mongodb://bla:bla@localhost:27017')['admin'].command('fsyncUnlock')

然而,这只锁定了写操作,这对我来说并没有削减它。

  1. 如何锁定读取?
  2. 我可以锁定集合,而不是整个数据库?
  3. 我现在认为我可以跳过查找,并做一个if collection.update_one().updated_count == 1: # do stuff...,虽然我不确定它是否完全解决了我需要的,因为没有find,我无法知道我更新的项目的id

参见MongoDB并发更新同一文档不表现原子的示例实现。

我可以锁定集合,而不是整个数据库吗?

试图用锁来解决并发问题(即使数据库不能被多个客户端使用)是次优的,因为它不能扩展,因此对于实际上具有并发性的情况是没有用的。

这就是为什么条件更新、MVCC/快照读取关注和类似的结构提供原子性一致性,但不提供锁定的原因。

最新更新