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. oracle的PDB启动

    /*以管理员身份登录*/sqlplus / as sysdba /*查看CDB的状态*/select status from v$instance; /*开启startup,默认是open*/star ...

  2. crontab定时执行shell脚本失败的原因

    有一段时间不用crontab定时执行任务了,这次趁着项目实施的机会来进一步分析一下crontab定时任务设置时遇到的一些棘手的问题. crontab -l 查看目前已经设置的crontab信息 cro ...

  3. mysql数据库的备份

    有时会遇到需要重装虚拟机的情况,这时候之前创建好的数据库就需要备份啦,等重新装好虚拟机直接导入就可以正常使用. 数据库备份大体分为两步: 第一步.导出数据库,因为是备份,会将所有的数据库导出,因此需要 ...

  4. CornerStone使用跳坑总结(陆续更新)

    Cornerstone是专门为Mac用户设计的Subversion(SVN)的控制,使版本控制更加透明.cornerstone根Xcode相比,能够更好的忽略文件,所以除了项目经理第一次初始化项目的时 ...

  5. String、StringBuilder、StringBuffer的区别

    这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面. 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > ...

  6. There is no getter for property named 'user' in 'class com.jyr.wh.domain.User' 异常

    今天在使用mybatis时,出现了一个问题:There is no getter for property named 'user' in 'class com.jyr.wh.domain.User, ...

  7. [LeetCode&Python] Problem 594. Longest Harmonious Subsequence

    We define a harmonious array is an array where the difference between its maximum value and its mini ...

  8. office2013 Word 缺少校对工具,按提示下载、安装了文件还是不成功的解决方案

    找到你的office安装源iso镜像加载 ——点开镜像双击setup.exe ——选择添加或删除功能 ——下一步——其他的不要动,展开office共享功能项 ——找到校对工具点出下拉项(点朝下的黑色箭 ...

  9. css flex方法标题左右两边平衡线

    <html> <div class="title"> <div class="line"></div> < ...

  10. [ZJOI2007]矩阵游戏【bzoj1059/洛谷1129】/ [HEOI2016/TJOI2016]游戏

    小QQ是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏.矩阵游戏在一个N \times NN×N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种 ...