MongoDB 读/写锁

Posted

技术标签:

【中文标题】MongoDB 读/写锁【英文标题】:MongoDB Read/Write Locks 【发布时间】:2014-12-25 15:40:02 【问题描述】:

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

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

我看过类似的问题,但我仍然感到困惑! mongodb 是一个不错的选择还是我应该只使用 Mysql?非常感谢您的帮助

【问题讨论】:

这个问题需要澄清一下。 “无法处理”到底是什么意思? @allTwentyQuestions 我的意思是在并发方面 mongo 是否会创建一个写入队列并等待每次写入完成后再开始下一个写入? 我认为您在这里遗漏了真正的问题。锁定很好,但是您可能会遇到隔离问题 - 正如您所说,如果多个用户尝试同时“投票”,您可能会遇到麻烦,具体取决于您如何实现。在 SO (***.com/questions/24808473/…) 中查看此问题和答案 【参考方案1】:

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

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

在更一般的意义上,MongoDB 使用writer-greedy reader-writer 锁,这样您就可以确定如果客户端 A 在客户端 B 读取文档之前更新了文档,那么 B 将看到 writer A 的更新。当然,其中一些将归结为驱动程序的实现以及您如何使用它,但对于任何数据库都是如此。

分布式环境

仅当您谈论的是 单个 实例时,上述内容才适用。一旦您有了 分布式 mongo 设置,我们就开始讨论 CAP theorem。 MongoDB 的一大特点是处理海量数据集的能力。这通常使用分片、副本集或两者来完成。在任何一种情况下,MongoDB 都被认为是最终一致的。在分布式设置中,客户端 B 可能会读取缺少客户端 A 更新的文档,因为 MongoDB 选择 Availability 而不是 Consistency。最终,所有这些不一致都会得到解决,实际上,对于大多数用例来说,它通常足够一致。但在分布式环境中设置时,它无法做出任何保证。

【讨论】:

【参考方案2】:

在 MongoDB 文档中的 Concurrency FAQ 中描述了锁定。特别是:

MongoDB 使用允许并发读取的读写锁 访问数据库,但提供对单个写入的独占访问权限 操作。

当存在读锁时,许多读操作可能会使用该锁。 但是,当存在写锁时,单个写操作会持有 独占锁定,并且没有其他读取或写入操作可以共享 锁。

锁是“写者贪婪的”,这意味着写锁有优先权 过读。当一个读和写都在等待一个锁时,MongoDB 授予写入锁定。

所以关于你的陈述:

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

MongoDB 使用数据库范围的锁来防止在数据库中某处执行写操作时进行读/写。从this JIRA item 看来,这将在未来简化为集合级别的锁(现在它只是在开发版本中)。此外,由于“作家贪婪”的方法,如果多个写入正在等待执行,它们将在任何读取之前完成,因此您的担忧不应该成为问题。

【讨论】:

2018年的事态值得一提——在wildtiger(mongo 3.2默认引擎)中,有文档级锁定。

以上是关于MongoDB 读/写锁的主要内容,如果未能解决你的问题,请参考以下文章

mongodb锁表怎么释放

MongoDB 监测

MongoDB 写入策略与读一致性

MongoDB,网上没有关于事务和读操作交互的信息

MongoDB系列四:解决secondary的读操作

(原创)让mongodb的secondary支持读操作