1. MongoDB 使用的锁

MongoDB 使用的是“readers-writer”锁, 可以支持并发但有很大的局限性
当一个读锁存在,许多读操作可以使用这把锁,然而, 当一个写锁的存在,一个单一的写操作会”exclusively“持有该锁,同一时间其它写操作不能使用共享这个锁;
举个例子,假设一个集合里有10个文档,多个update操作不能并发在这个集合上,即使是更新不同的文档。

2. 锁的粒度

在 2.2 版本以前,一个mongodb实例一个写锁,多个读锁。也就是说mongod 只有全局锁(锁定一个server);

在2.2-3.0的版本,一个数据库一个写锁,多个读锁。例如如果一个 mongod 实例上有 5 个库,如果只对一个库中的一个集合执行写操作,那么在写操作过程中,这个库被锁;而其它 4 个库不影响。相比 RDBMS 来说,这个粒度已经算很大了!

在3.0之后的版本,WiredTiger提供了文档(不是集合)级别的锁。

更新:MongoDB
3.4版本,写操作的锁定粒度在表中数据记录(document)级别,即使操作对象可能是多条数据,每条数据在被写入时都会被锁定,防止其他进程写入;但是写操作是非事务性的,即写入多条数据,即使当前写入操作还没有完成,前面已经写入的数据也可以被其他进程修改。除非指定了$isolated,一次写入操作影响的数据无法在本次操作结束之前被其他进程修改。
$isolated也是非事务性的,即如果写入过程出错,已经完成的写入操作不会被rollback;另外,$isolated需要额外的锁,无法用于sharded方式部署的集群。
官网文档链接

MongoDB高吞吐的原因:

  • MongoDB 没有完整事务支持,操作原子性只到单个 document 级别,所以通常操作粒度比较小;
  • MongoDB 锁实际占用时间是内存数据计算和变更时间,通常很快;
  • MongoDB 锁有一种临时放弃机制,当出现需要等待慢速 IO 读写数据时,可以先临时放弃,等 IO 完成之后再重新获取锁。

3. 如何查看锁的状态

db.serverStatus()
db.currentOp()
mongotop # 类似top命令,每秒刷新
mongostat
the MongoDB Monitoring Service (MMS)

4. 哪些操作会对数据库产生锁?

下表列出了常见数据库操作产生的锁。

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

附上原文:
Operation Lock Type
Issue a query Read lock
Get more data from a cursor Read lock
Insert data Write lock
Remove data Write lock
Update data Write lock
Map-reduce
Read lock and write lock, unless operations are specified as
non-atomic. Portions of map-reduce jobs can run concurrently.
Create an index Building an index in the foreground, which is the default, locks the database for extended periods of time.
db.eval() Write lock. db.eval() blocks all other JavaScript processes.
eval
Write lock. If used with the nolock lock option, the eval option
does not take a write lock and cannot write data to the database.
aggregate() Read lock

5. 哪些数据库管理操作会锁数据库?

某些数据库管理操作会 exclusively 锁住数据库,以下命令需要申请 exclusively 锁,并锁定一段时间

db.collection.ensureIndex(),
reIndex,
compact,
db.repairDatabase(),
db.createCollection(), when creating a very large (i.e. many gigabytes) capped collection,
db.collection.validate(),
db.copyDatabase() # 可能会锁定所有数据库(database)


以下命令需要申请 exclusively 锁,但锁定很短时间。

db.collection.dropIndex(),
db.collection.getLastError(),
db.isMaster(),
rs.status() (i.e. replSetGetStatus,)
db.serverStatus(),
db.auth(), and
db.addUser().

备注:可见,一些查看命令也会锁库,在比较繁忙的生产库中,也会有影响的。

6. MongoDB内部可能锁住所有库的操作

以下数据库内部操作会锁定多个库。

日志管理 MongoDB的内部操作,每个一段时间就锁定所有数据库,所有的数据库共享一份日志
用户认证 锁定admin数据库和用户正在申请访问的数据库
所有写入备份数据库(replica)的操作都会锁定写入目标数据库和本地数据库,本地数据库的写入锁允许写入主节点的oplog

原文:
Journeying, which is an internal operation, locks all databases for short intervals. All databases share a single journal.
User authentication locks the admin database as well as the database the user is accessing.
All
writes to a replica set’s primary lock both the database receiving the
writes and the local database. The lock for the local database allows
the mongod to write to the primary’s oplog.

MongoDB中的读写锁的更多相关文章

  1. java多线程:并发包中ReentrantReadWriteLock读写锁的原理

    一:读写锁解决的场景问题--->数据的读取频率远远大于写的频率的场景,就可以使用读写锁.二:读写锁的结构--->用state一个变量.将其转化成二进制,前16位为高位,标记读线程获取锁的次 ...

  2. java中ReentrantReadWriteLock读写锁的使用

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...

  3. Java 并发包中的读写锁及其实现分析

    1. 前言 在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时 刻可以允许多个读线程访问,但是在写线程访问时,所有 ...

  4. Java中的读写锁

    一.读写锁 1.初识读写锁 a)Java中的锁——Lock和synchronized中介绍的ReentrantLock和synchronized基本上都是排它锁,意味着这些锁在同一时刻只允许一个线程进 ...

  5. go中的读写锁RWMutex

    读写锁是针对于读写操作的互斥锁. 基本遵循两大原则: 1.可以随便读.多个goroutin同时读. 2.写的时候,啥都不能干.不能读,也不能写. 解释: 在32位的操作系统中,针对int64类型值的读 ...

  6. 线程中的读写锁ReadWriteLock

    Lock锁还有两个非常强大的类 ReadWriteLock接口实现类ReentrantReadWriteLock(非常重要的锁) 想实现 读取的时候允许多线程并发访问,写入的时候不允许. 这种效果.. ...

  7. java中的读/写锁

    读写锁接口:ReadWriteLock,它的具体实现类为:ReentrantReadWriteLock 使用场景: 对于一个资源,读读能共存,读写不能共存,写写不能共存. 锁降级:从写锁变成读锁: 锁 ...

  8. 22、Java并发性和多线程-Java中的读/写锁

    以下内容转自http://ifeve.com/read-write-locks/: 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些.假设你的程序中涉及到对一些共享资源 ...

  9. java多线程:并发包中ReentrantReadWriteLock读写锁的锁降级模板

    写锁降级为读锁,但读锁不可升级或降级为写锁. 锁降级是为了让当前线程感知到数据的变化. //读写锁 private ReentrantReadWriteLock lock=new ReentrantR ...

随机推荐

  1. 微信小程序 - app.json配置解析

    { "pages": [ "pages/index/index", "pages/logs/logs", "pages/login ...

  2. 常见的CSS

    /***** Selector Hacks ******/ /* IE6 and below */ * html #uno { color: red } /* IE7 */ *:first-child ...

  3. Spring XML文件配置

    singleton不能创建多对象(默认) <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...

  4. HTML5 Canvas爱心时钟代码

    这是一款数字时钟动画,数字又多个小爱心组成,又何问起整理,随着时间推进,每一秒钟新数字替换旧数字,旧数字离去使用天女散花动画,花是五颜六色的. 查看效果:http://hovertree.com/te ...

  5. Sql Server 默认值

    --1.取得数据库所有表的默认值: select t3.name as 表名,t1.name as 字段名,t2.text as 默认值 ,t4.name from syscolumns t1,sys ...

  6. 自动删除Android工程中无用的资源

    开发时间久了, 几个版本迭代之后, 工程中难免留下很多垃圾资源, 造成apk的包很大, 这里介绍一个工具, 可以自动扫描工程中, 没有使用的资源, 然后自动删除: 包括图片, xml, 文本等. 采用 ...

  7. Java日志框架

    1.Logback 默认情况下springboot是不将日志输出到日志文件中,这里对日志框架的支持有两种配置方式: application.properties 或 application.yml ( ...

  8. python基础(五)

    一.os模块 import os# os.rename(old,new)#重命名# os.remove(f)#删除文件 # os.mkdir('china/beijing') #创建文件夹# os.m ...

  9. 腾讯地图api 地址解析 js版

    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" ...

  10. 报文 HTTP HTTPS

    报文是网络中交换与传输的数据单元,即站点一次性要发送的数据块.报文包含了将要发送的完整的数据信息,其长短很不一致,长度不限且可变. 报文也是网络传输的单位,传输过程中会不断的封装成分组.包.帧来传输, ...