简介
MongoDB 不提供锁定文档的方法(如 RDBMS 中的 SELECT FOR UPDATE)。
建议使用 Isolate Sequence of Operations 的方法,有时称为乐观锁定,但在某些情况下,这种方法似乎过于复杂甚至效率低下(这就是悲观锁仍在使用的原因)。
任务
我想在应用程序级别实现通用文档锁定。假设我只有一个与集合相关的应用程序。我的应用程序是多线程。
使用场景:
with DocumentLock(doc_id):
# make sure no other thread interferes
doc=db.doc_collection.find_one(doc_id)
... # analyse and update the document
db.doc_collection.save(doc)
问题
您会为该任务推荐什么解决方案?
最佳答案
这是我的 DocumentLock 类:
class DocumentLock(object):
_lock=RLock() # protects access to _locks dictionary
_locks=WeakValueDictionary()
def __init__(self, doc_id):
self.doc_id=doc_id
def __enter__(self):
with self._lock:
self.lock=self._locks.get(self.doc_id)
if self.lock is None:
self._locks[self.doc_id]=self.lock=RLock()
self.lock.acquire()
def __exit__(self, exc_type, exc_value, traceback):
self.lock.release()
self.lock=None # make available for garbage collection
所以基本上我有一本 RLock 字典,每个访问的文档一个 RLock。我使用弱引用来摆脱未使用的锁。
DocumentLock 可以为每个需要记录锁定的集合(或表)进行子类化。
这一切似乎都有效(尽管没有在并发下进行测试),但我不确定这种方法没有弱点,或者是否有更好的方法。
关于Python 应用程序级文档/记录锁定(例如,对于 MongoDB),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20155533/