MongoDB 将写入锁定到什么级别?(或:“每个连接”是什么意思
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17456671/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
To what level does MongoDB lock on writes? (or: what does it mean by "per connection"
提问by nicksahler
In the mongodb documentation, it says:
在 mongodb 文档中,它说:
Beginning with version 2.2, MongoDB implements locks on a per-database basis for most read and write operations. Some global operations, typically short lived operations involving multiple databases, still require a global “instance” wide lock. Before 2.2, there is only one “global” lock per mongod instance.
从 version 2.2 开始,MongoDB 为大多数读取和写入操作在每个数据库的基础上实现锁。一些全局操作,通常是涉及多个数据库的短期操作,仍然需要全局“实例”范围的锁。在 2.2 之前,每个 mongod 实例只有一个“全局”锁。
Does this mean that in the situation that I Have, say, 3 connections to mongodb://localhost/test from different apps running on the network - only one could be writing at a time? Or is it just per connection?
这是否意味着在我有 3 个连接到 mongodb://localhost/test 从网络上运行的不同应用程序的情况下 - 一次只能写入一个?还是只是每个连接?
IOW: Is it per connection, or is the whole /test database locked while it writes?
IOW:是每个连接,还是在写入时整个 /test 数据库被锁定?
采纳答案by Sammaye
It is not per connection, it is per mongod
. In other words the lock will exist across all connections to the test
database on that server.
它不是每个连接,而是每个mongod
. 换句话说,该锁将存在于到该test
服务器上的数据库的所有连接中。
It is also a read/write lock so if a write is occuring then a read must wait, otherwise how can MongoDB know it is a consistent read?
它也是一个读/写锁,所以如果一个写正在发生,那么一个读必须等待,否则 MongoDB 怎么知道它是一个一致的读?
However I should mention that MongoDB locks are very different to SQL/normal transactional locks you get and normally a lock will be held for about a microsecond between average updates.
但是,我应该提到 MongoDB 锁与您获得的 SQL/普通事务锁非常不同,通常在平均更新之间,锁会保持大约一微秒。
回答by William Z
MongoDB Locking is Different
MongoDB 锁定是不同的
Locking in MongoDB does not work like locking in an RDBMS, so a bit of explanation is in order. In earlier versions of MongoDB, there was a single global reader/writer latch. Starting with MongoDB 2.2, there is a reader/writer latch for each database.
MongoDB 中的锁定不像 RDBMS 中的锁定那样工作,因此需要进行一些解释。在早期版本的 MongoDB 中,只有一个全局读取器/写入器闩锁。从 MongoDB 2.2 开始,每个数据库都有一个读/写锁存器。
The readers-writer latch
读写锁存器
The latch is multiple-reader, single-writer, and is writer-greedy. This means that:
锁存器是多读取器、单写入器,并且是写入器贪婪的。这意味着:
- There can be an unlimited number of simultaneous readers on a database
- There can only be one writer at a time on any collection in any one database (more on this in a bit)
- Writers block out readers
- By "writer-greedy", I mean that once a write request comes in, all readers are blocked until the write completes (more on this later)
- 一个数据库上可以有无限数量的并发读者
- 任何一个数据库中的任何集合一次只能有一个作者(稍后会详细介绍)
- 作家挡住了读者
- “写入者贪婪”是指一旦写入请求进入,所有读取器都会被阻塞,直到写入完成(稍后会详细介绍)
Note that I call this a "latch" rather than a "lock". This is because it's lightweight, and in a properly designed schema the write lock is held on the order of a dozen or so microseconds. See herefor more on readers-writer locking.
请注意,我称其为“闩锁”而不是“锁”。这是因为它是轻量级的,并且在设计合理的模式中,写锁保持在十几微秒的数量级。有关读者-作者锁定的更多信息,请参见此处。
In MongoDB you can run as many simultaneous queries as you like: as long as the relevant data is in RAM they will all be satisfied without locking conflicts.
在 MongoDB 中,您可以运行任意数量的并发查询:只要相关数据在 RAM 中,它们都会得到满足,而不会发生锁定冲突。
Atomic Document Updates
原子文档更新
Recall that in MongoDB the level of transaction is a single document. All updates to a single document are Atomic. MongoDB achieves this by holding the write latch for only as long as it takes to update a single document in RAM. If there is any slow-running operation (in particular, if a document or an index entry needs to be paged in from disk), then that operation will yieldthe write latch. When the operation yields the latch, then the next queued operation can proceed.
回想一下,在 MongoDB 中,事务级别是单个文档。对单个文档的所有更新都是原子的。MongoDB 通过仅在更新 RAM 中的单个文档所需的时间内保持写锁存器来实现这一点。如果有任何运行缓慢的操作(特别是,如果需要从磁盘调入文档或索引条目),则该操作将产生写锁存器。当操作产生锁存器时,下一个排队的操作就可以继续进行。
This does mean that the writes to all documents within a single database get serialized. This can be a problem if you have a poor schema design, and your writes take a long time, but in a properly-designed schema, locking isn't a problem.
这确实意味着对单个数据库中所有文档的写入被序列化。如果您的架构设计不佳,并且您的写入需要很长时间,这可能会成为一个问题,但在设计合理的架构中,锁定不是问题。
Writer-Greedy
贪婪的作家
A few more words on being writer-greedy:
关于作家贪婪的更多话:
Only one writer can hold the latch at one time; multiple readers can hold the latch at a time. In a naive implementation, writers could starve indefinitely if there was a single reader in operation. To avoid this, in the MongoDB implementation, once any single thread makes a write request for a particular latch
一次只有一个写者可以持有锁存器;多个读者可以一次持有闩锁。在一个简单的实现中,如果只有一个读取器在运行,写入器可能会无限期地饿死。为了避免这种情况,在 MongoDB 实现中,一旦任何单个线程对特定锁存器发出写请求
- All subsequent readers needing that latch will block
- That writer will wait until all current readers are finished
- The writer will acquire the write latch, do its work, and then release the write latch
- All the queued readers will now proceed
- 需要该闩锁的所有后续读取器都将阻塞
- 该作者将等到所有当前读者都读完
- 写入器将获取写锁存器,完成其工作,然后释放写锁存器
- 所有排队的读者现在将继续
The actual behavior is complex, since this writer-greedy behavior interacts with yielding in ways that can be non-obvious. Recall that, starting with release 2.2, there is a separatelatch for each database, so writes to any collection in database 'A' will acquire a separate latch than writes to any collection in database 'B'.
实际的行为是复杂的,因为这种贪婪的作者行为以不明显的方式与 yield 相互作用。回想一下,从 2.2 版开始,每个数据库都有一个单独的锁存器,因此写入数据库 'A' 中的任何集合将获得一个单独的锁存器,而不是写入数据库 'B' 中的任何集合。
Specific questions
具体问题
Regarding the specific questions:
关于具体问题:
- Locks (actually latches) are held by the MongoDB kernel for only as long as it takes to update a single document
- If you have multiple connections coming in to MongoDB, and each one of them is performing a series of writes, the latch will be held on a per-database basis for only as long as it takes for that write to complete
- Multiple connections coming in performing writes (update/insert/delete) will all be interleaved
- 锁(实际上是闩锁)由 MongoDB 内核持有,仅在更新单个文档所需的时间内
- 如果您有多个连接进入 MongoDB,并且每个连接都在执行一系列写入,则闩锁将在每个数据库的基础上保持,只要该写入完成所需的时间
- 执行写入(更新/插入/删除)的多个连接将全部交错
While this sounds like it would be a big performance concern, in practice it doesn't slow things down. With a properly designed schema and a typical workload, MongoDB will saturate the disk I/O capacity -- even for an SSD -- before lock percentage on any database goes above 50%.
虽然这听起来像是一个很大的性能问题,但实际上它不会减慢速度。借助设计合理的架构和典型的工作负载,MongoDB 将在任何数据库的锁定百分比超过 50% 之前使磁盘 I/O 容量饱和——即使对于 SSD 也是如此。
The highest capacity MongoDB cluster that I am aware of is currently performing 2 million writes per second.
我所知道的最高容量的 MongoDB 集群目前每秒执行 200 万次写入。
回答by Londo
Mongo 3.0 now supports collection-level locking.
Mongo 3.0 现在支持集合级锁定。
In addition to this, now Mongo created an API that allows to create a storage engine. Mongo 3.0 comes with 2 storage engines:
除此之外,现在 Mongo 创建了一个允许创建存储引擎的 API。Mongo 3.0 带有 2 个存储引擎:
- MMAPv1: the default storage engine and the one use in the previous versions. Comes with collection-level locking.
- WiredTiger: the new storage engine, comes with document-level locking and compression. (Only available for the 64-bit version)
- MMAPv1:默认存储引擎,在之前的版本中使用。带有集合级锁定。
- WiredTiger:新的存储引擎,带有文档级锁定和压缩。(仅适用于 64 位版本)
回答by Muhammad Ali
I know the question is pretty old but still some people are confused....
我知道这个问题已经很老了,但仍然有些人感到困惑......
Starting in MongoDB 3.0, the WiredTiger storage engine (which uses document-level concurrency) is available in the 64-bit builds.
WiredTiger uses document-level concurrency control for write operations. As a result, multiple clients can modify different documents of a collection at the same time.
For most read and write operations, WiredTiger uses optimistic concurrency control. WiredTiger uses only intent locks at the global, database and collection levels. When the storage engine detects conflicts between two operations, one will incur a write conflict causing MongoDB to transparently retry that operation.
Some global operations, typically short lived operations involving multiple databases, still require a global “instance-wide” lock. Some other operations, such as dropping a collection, still require an exclusive database lock.
从 MongoDB 3.0 开始,WiredTiger 存储引擎(使用文档级并发)在 64 位版本中可用。
WiredTiger 对写操作使用文档级并发控制。因此,多个客户端可以同时修改集合的不同文档。
对于大多数读写操作,WiredTiger 使用乐观并发控制。WiredTiger 仅在全局、数据库和集合级别使用意图锁。当存储引擎检测到两个操作之间存在冲突时,会引发写入冲突,导致 MongoDB 透明地重试该操作。
一些全局操作,通常是涉及多个数据库的短期操作,仍然需要全局“实例范围”锁。其他一些操作,例如删除集合,仍然需要排他数据库锁。