6.3.5 MongoDB的并发控制
MongoDB允许多个客户端读取和写入相同的数据。为了确保一致性,它使用锁定和其他并发控制措施来防止多个客户端同时修改同一数据。这些机制共同保证了对单个文档的所有写入全部发生或完全不发生,并且客户永远不会看到不一致的数据视图。
MongoDB使用多粒度锁定,它允许操作锁定在全局,数据库或集合级别,并允许各个存储引擎在集合级别以下实现自己的并发控制。
MongoDB使用读取器-写入器锁,允许并发的读取器共享对资源(例如数据库或集合)的访问。除了用于读取的共享(S)锁定模式和用于写操作的互斥(X)锁定模式之外,意图共享(IS)和意图互斥(IX)模式还表示使用更精细的粒度锁来读取或写入资源的意图。当以一定的粒度锁定时,所有更高级别的锁定都使用意图锁来锁定。
例如,当锁定用于写的集合(使用模式X)时,必须将所有数据库锁和全局锁都锁定为意图排他(IX)模式。可以在IS和IX模式下同时锁定单个数据库,但是独占(X)锁不能与任何其他模式共存,共享(S)锁只能与意图共享(IS)锁共存。
对于大多数读取和写入操作,WiredTiger(MongoDB3.0以后使用的默认的存储引擎)使用乐观并发控制。WiredTiger仅在全局,数据库和集合级别使用意图锁。当存储引擎检测到两个操作之间存在冲突时,将引发写冲突,从而导致MongoDB透明地重试该操作。一些全局操作(通常是涉及多个数据库的短暂操作)仍然需要全局“实例范围”锁。某些其他操作(例如collMod)仍需要排他数据库锁定。
在分片群集中,锁适用于每个单独的分片,而不适用于整个群集。也就是说,每个mongod实例都独立于分片群集中的其他实例,并使用自己的锁。一个mongod实例上的操作不会阻止任何其他实例上的操作。
对于副本集,当MongoDB写入主数据库上的集合时,MongoDB还将写入主数据库的操作日志,这是local数据库中的特殊集合。因此,MongoDB必须同时锁定集合的数据库和local数据库。在MongoDB必须同时保持数据库一致,并确保写入操作,即使复制锁定两个数据库,分别是“全有或全无”的操作。写入副本集时,锁的范围适用于主节点。