MongoDBlocking在什么级别写入? (或者:“每个连接”意味着什么

在mongodb文档中,它说:

从版本2.2开始,对于大多数读写操作,MongoDB基于每个数据库实现locking。 一些全球性操作,通常是涉及多个数据库的短期操作,仍然需要全局“实例”locking。 在2.2之前,每个mongod实例只有一个“全局”锁。

这是否意味着,在我所拥有的情况下,例如,从networking上运行的不同应用程序连接到mongodb:// localhost / test – 只能有一次写入? 还是只是每个连接?

IOW:是每个连接,还是整个/testing数据库在写入时被locking?

这不是每个连接,而是每个mongod 。 换句话说,该锁将存在于该服务器上的test数据库的所有连接上。

它也是一个读/写锁,所以如果发生写操作,读操作必须等待,否则MongoDB怎么知道它是一致的读?

不过,我应该提到的是,MongoDB锁与您获得的SQL /正常事务锁非常不同,通常锁之间的平均更新间隔约为1微秒。

MongoDBlocking是不同的

在MongoDB中locking不能像lockingRDBMS一样工作,所以需要一点解释。 在早期版本的MongoDB中,只有一个全局读写器锁存器。 从MongoDB 2.2开始,每个数据库都有一个读/写锁存器。

读写器锁存器

该锁是多个读者,单个作家,并且是写作贪婪的。 这意味着:

  • 在数据库上可以有无限数量的同步阅读器
  • 在任何一个数据库的集合中,一次只能有一个作者(更多的是这个)
  • 作家挡住读者
  • “写作者贪婪”是指一旦有写入请求进入,所有的读者都被阻塞,直到写入完成(稍后再进一步)

请注意,我称之为“锁”,而不是“锁”。 这是因为它是轻量级的,并且在devise合理的模式下,写入locking保持在十几个微秒左右。 有关读者 – 写者locking的更多信息,请参阅这里

在MongoDB中,您可以随心所欲地运行尽可能多的同时查询:只要相关数据在RAM中,它们都将被满足而不会发生locking冲突。

primefaces文档更新

回想一下,在MongoDB中,事务级别是单个文档。 对单个文档的所有更新都是Atomic。 MongoDB通过只需要更新RAM中的单个文档就可以保持写锁存器来实现这一点。 如果有缓慢运行的操作(特别是,如果文档或索引条目需要从磁盘中分页),则该操作将产生写锁存器。 当操作产生闩锁时,下一个排队的操作可以继续。

这意味着对单个数据库中的所有文档的写入操作都会被序列化。 这可能是一个问题,如果你有一个糟糕的模式devise,你的写入需要很长的时间,但在一个devise合理的模式,locking不是一个问题。

作家贪婪

关于作家贪婪的几句话:

只有一个作家可以一次抓住门闩; 多个读卡器一次可以锁住。 在一个天真的实现中,如果只有一个阅读器在运行,作者可能会无限期地饿死。 为了避免这种情况,在MongoDB实现中,一旦任何一个线程对特定的锁存器发出写入请求

  • 所有需要该锁存器的随后读取器将被阻止
  • 那位作家会等到所有的读者都完成了
  • 作者将获得写锁存器,完成其工作,然后释放写锁存器
  • 所有排队的读者现在将继续

实际的行为是复杂的,因为这个作家贪婪的行为以非常明显的方式与屈服相互作用。 回想一下,从版本2.2开始,每个数据库都有一个独立的锁存器,因此写入数据库“A”中的任何集合将获得一个单独的锁存器,而不是写入数据库“B”中的任何集合。

具体的问题

关于具体问题:

  • 只有更新单个文档时,锁(实际上锁存器)才由MongoDB内核保存
  • 如果有多个连接进入MongoDB,并且每个连接都在执行一系列写操作,则锁存器将按照每个数据库的方式进行保存,只要这个写操作完成
  • 执行写入(更新/插入/删除)的多个连接将全部交错

虽然这听起来像是一个很大的性能问题,但在实践中它并没有减慢速度。 通过devise合理的模式和典型的工作负载,MongoDB将在磁盘I / O容量饱和的情况下(即使是SSD),在任何数据库的locking百分比超过50%之前。

目前我知道的容量最高的MongoDB集群每秒钟执行200万次写入。

Mongo 3.0现在支持集合级locking。

除此之外,现在Mongo创build了一个允许创build存储引擎的API。 Mongo 3.0带有2个存储引擎:

  1. MMAPv1 :默认存储引擎,以及之前版本中使用的引擎。 带有收集级locking。
  2. WiredTiger :新的存储引擎,带有文档级locking和压缩function。 (仅适用于64位版本)

MongoDB 3.0发行说明

WiredTiger

我知道这个问题是相当古老的,但仍然有些人是困惑….

从MongoDB 3.0开始,WiredTiger存储引擎(使用文档级并发 )在64位版本中可用。

WiredTiger使用文档级并发控制进行写操作。 因此,多个客户端可以同时修改集合的不同文档。

对于大多数读写操作,WiredTiger使用乐观并发控制。 WiredTiger仅在全局,数据库和集合级别使用意向锁。 当存储引擎检测到两个操作之间存在冲突时,会引发写冲突,导致MongoDB透明地重试该操作。

一些全球性操作(通常涉及多个数据库的短期操作)仍然需要全局“实例范围”locking。 其他一些操作(如删除集合)仍需要独占数据库locking。

文档级并发性