MongoDB:锁和并发控制
本文主要介绍两部分内容,第一部分是MongoDB的锁,第二部分是MongoDB的并发控制。这都跟MongoDB性能和效率相关的,有助于在使用MongoDB过程中,知道哪些操作会带来怎样效率的影响。第二部分从业务层面出发介绍并发控制的方法,基本上都是开发中碰到的常见场景。
MongoDB锁
###锁类型
Mongodb使用的是read-write读写锁,允许多个读者并发的加共享锁访问同一资源,而同一时间只允许一个写者加排它锁改变资源,此时不允许其它的读和写。
在mongodb中,还使用了意向锁(IS、IX)提高加锁性能。为了提高吞吐率,在等待排队的锁中,排在最前面的如果是共享锁,会一次把队列中所有的共享锁都加上,释放之后就处理排他锁。而不是当前是共享锁,后面一来共享锁请求都加上去,后面的请求是要排队的,避免写锁的饥饿。
锁的粒度
mongodb普遍使用全局锁、数据库锁。还允许自己使用不同存储引擎,实现更细粒度的锁控制。比如MMAPv1存储引擎支持表锁,WiredTiger存储引擎,支持文档级别的锁。
在 2.2 版本以前,mongodb只有全局锁;也就是对整个mongodb实例加锁,这个粒度是很大的。
从 2.2 版本开始,大部分读写操作只锁一个库,库级别锁相对之前版本,这个粒度已经下降。对于一些涉及到多个数据库操作,还需要加全局锁。目前MongoDB常见的版本是2.6、2.7,锁粒度只到collection。
从 3.0 开始,如果使用MMAPv1存储引擎,最细粒度支持 collection级别的锁 ,对于一个数据库里面的collection,对一个collection的加锁操作,不影响其他collection的操作。
查看锁的状态
产生加锁的操作操作锁类型query读锁
cursor get more读锁
insert写锁
remove写锁
update写锁
Map-reduce读锁和写锁,除非Map-reduce操作被声明为非原子性的。部分map-reduce任务能够并发的执行。
createIndex创建索引操作默认在前台执行,会长时间锁住数据库。
db.eval()写锁 db.eval()会加全局写锁,会阻塞其他的读写操作。加上参数nolock: true,表示不加锁。
eval写锁. 同db.eval()
aggregate()读锁
<