MongoDB锁

MongoDB锁教程

MongoDB 使用的是 “readers-writer” 锁, 可以支持并发但有很大的局限性。当一个读锁存在,许多读操作可以使用这把锁,然而, 当一个写锁的存在,一个单一的写操作会 ”exclusively“ 持有该锁,同一时间其它写操作不能使用共享这个锁。

举个例子,假设一个集合里有 10 个文档,多个 update 操作不能并发在这个集合上,即使是更新不同的文档。

MongoDB锁的粒度

在 2.2 版本以前,mongod 只有全局锁(锁定一个 server)。

从 2.2 版本开始,大部分读写操作只锁一个库(database),相对之前版本,这个粒度已经下降,例如如果一个 mongod 实例上有 5 个库,如果只对一个库中的一个集合执行写操作,那么在写操作过程中,这个库被锁;而其它 5 个库不影响。相比 RDBMS 来说,这个粒度已经算很大了!

MongoDB 3.4 版本,写操作的锁定粒度在表中数据记录(document)级别,即使操作对象可能是多条数据,每条数据在被写入时都会被锁定,防止其他进程写入;但是写操作是非事务性的,即写入多条数据,即使当前写入操作还没有完成,前面已经写入的数据也可以被其他进程修改。除非指定了 $isolated,一次写入操作影响的数据无法在本次操作结束之前被其他进程修改。

isolated 也是非事务性的,即如果写入过程出错,已经完成的写入操作不会被 rollback;另外,isolated 需要额外的锁,无法用于 sharded 方式部署的集群。

MongoDB查看锁的状态

语法

db.serverStatus() db.currentOp()

说明

使用 serverStatus 或者使用 currentOp 都可以查看锁状态。

MongoDB锁产生

操作 锁定类型
查询 读锁
通过cursor读取数据 读锁
插入数据 写锁
删除数据 写锁
修改数据 写锁
Map-reduce 读写锁均有,除非指定为non-atomic,部分mapreduce任务可以同时执行(猜测是生成的中间表不冲突的情况下)
添加index 通过前台API添加index,锁定数据库一段时间
db.eval() 写锁,同时阻塞其他运行在MongoDB上的JavaScript进程
eval 写锁,如果设定锁定选项是nolock,则不会有些锁,而且eval无法向数据库写入数据
aggregate() 读锁

MongoDB锁总结

MongoDB 使用的是 “readers-writer” 锁, 可以支持并发但有很大的局限性。当一个读锁存在,许多读操作可以使用这把锁,然而, 当一个写锁的存在,一个单一的写操作会 ”exclusively“ 持有该锁,同一时间其它写操作不能使用共享这个锁。

举个例子,假设一个集合里有 10 个文档,多个 update 操作不能并发在这个集合上,即使是更新不同的文档。