MongoDB 读/写锁

8

我计划使用nodejs创建一个应用程序,让用户对产品进行评分。据我所知,mongodb中的锁与mysql不同。

我担心如果有10个用户同时对一个产品进行投票,Mongodb无法处理,其他用户看到的结果可能不正确。

我查看了类似的问题,但仍然感到困惑!MongoDB是一个好选择还是应该只使用MySQL?感谢您的帮助。


1
这个问题需要进一步澄清。你所说的“无法处理”,具体指什么? - allTwentyQuestions
@allTwentyQuestions 我的意思是在并发方面,Mongo是否会创建一个写入队列,并在开始下一个写入之前等待每个写入完成? - Hirad Roshandel
我认为您在这里忽略了真正的问题。锁定是好的,但是您可能会面临隔离问题 - 就像您所说的,如果多个用户同时尝试“投票”,则可能会遇到麻烦,这取决于您如何实现事情。请在stackoverflow上检查此问题和答案(https://dev59.com/H4Hba4cB1Zd3GeqPTp9e?rq=1) - joao
2个回答

9

在MongoDB文档的并发FAQ中介绍了锁定。特别是:

MongoDB使用读写锁,允许对数据库进行并发读取操作,但只允许单个写操作进行独占式访问。

当存在读锁时,许多读操作可以使用此锁。然而,当存在写锁时,单个写操作将独占地持有锁,没有其他读或写操作可以共享该锁。

锁是“写入优先”,这意味着写入锁具有优先权而不是读取。当一个读和一个写都在等待锁时,MongoDB将锁授予写入。

因此,关于您的陈述:

Mongodb无法处理它,其他用户看到的结果不正确。

MongoDB采用数据库级锁定,防止在数据库的某个位置执行写操作时进行读/写操作。从this JIRA item看来,这将在未来减少到集合级别锁定(现在仅适用于开发版本)。此外,由于“写入者贪婪”方法,如果有多个写操作等待执行,则会在任何读取之前执行它们,因此您不必担心。

3
2018年的事态值得一提 - 在Mongo 3.2的默认引擎wildtiger中,存在文档级别的锁定。 - knopch1425

4

任何对于单个文档的写操作都保证是原子性的。它要么完全成功,要么完全失败,并且请求同一文档的客户端将获得一个处于一致状态的该文档副本。

对于批量操作,默认情况下不是这种情况。通常,如果您在单个操作中更新了10个文档,则其他操作可能会在更新之间交错。您可以使用$isolated运算符来隔离操作,以确保没有人能够以不一致的状态查看那组文档。

在更一般的意义上,MongoDB使用writer-greedy读者-写者锁,因此您可以相当确定,如果客户端A在客户端B读取它之前更新了一个文档,则B将看到作者A的更新。当然,其中一些要归结于驱动程序的实现方式及其使用方式,但这对于任何数据库都是正确的。

分布式环境

以上仅适用于单个实例。一旦您拥有分布式的MongoDB设置,我们就开始谈论CAP定理。 MongoDB的一个伟大特性是它能够很好地扩展以处理巨大的数据集。通常使用分片、副本集或两者来实现这一点。在任何这些情况下,MongoDB都被称为是“最终一致”的。在分布式设置中,客户端B可能会读取缺少客户端A更新的文档,因为MongoDB选择了可用性而不是一致性。最终,所有这些不一致之处都将得到解决,在实践中,它通常对大多数用例而言足够一致。但在分布式环境中设置时无法做出任何保证。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接