Mongodb锁机制
Mongodb使用读写锁来允许很多用户同时去读一个资源,比如数据库或者集合。读采用的是共享锁,写采用的是排它锁。
对于大部分的读写操作,WiredTiger使用的都是乐观锁,在全局、数据库、集合级别,WiredTiger使用的是意向锁。当引擎探测到两个操作之间发生了冲突,将会产生一个写冲突,mongodb将会重新执行操作。只有如删除集合等操作需要排它锁。
查看lock情况
如果查看在Mongod实例中的lock情况,可以使用如下方式:
1. db.serverStatus
2. db.currentOp
3. mongotop
4. mongostat
5. locks集合
读写是否会造成锁
在长时间的读写操作,如查询、更新或者删除,mongodb同样会产生锁。比如在很多条件下的多个文档的更新会产生锁。下面这些操作将会锁住db:
操作 | 锁类别 |
---|---|
查询 | 读 |
从游标中getMore | 读 |
写入数据 | 写 |
删除数据 | 写 |
更新数据 | 写 |
map-reduce | 读写 |
创建索引 | 默认的是前台创建索引,将锁住整个db |
eval | 全局锁,除非使用nolock:true |
aggregate | 读 |
全局锁
在一些admin的命令中,排它锁会在某一段时间内锁住整个数据库。所以最好在离线下执行。如下会使用全局锁
- createIndex
- repairDatabase
- copyDatabase
- compact
短时间内锁住db的操作有:
- auth
- 所有写到副本集primary的写操作,将会同时锁住local数据库,其中local数据库主要存放的是副本集的配置信息,oplog信息,这些信息是存在本地的,不会同步到其它的节点,即当该节点发生了故障所有的数据都将会丢失,所以不要讲数据放在local数据库中,同样的,在admin中如果存放定义的集合,它是不支持集合锁的,将会锁住整个db,直接影响性能
分片的同步
在一个分片集群中,锁会应用到单个分片中,而不是整个集群。也即每个Mongod实例在shard集群中是独立的,拥有自己的Lock,在某个mongod中的操作不会阻塞其它的shard。
副本集的同步
在副本集的情况下,mongodb向主节点写入数据,同样会写到oplog中,会lock住primary,对于从节点,数据以batch方式写入,并且向不同的从节点写入是以并行的方式进行。