MongoDB中的读写锁
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中的读写锁的更多相关文章
- java多线程:并发包中ReentrantReadWriteLock读写锁的原理
一:读写锁解决的场景问题--->数据的读取频率远远大于写的频率的场景,就可以使用读写锁.二:读写锁的结构--->用state一个变量.将其转化成二进制,前16位为高位,标记读线程获取锁的次 ...
- java中ReentrantReadWriteLock读写锁的使用
Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...
- Java 并发包中的读写锁及其实现分析
1. 前言 在Java并发包中常用的锁(如:ReentrantLock),基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时 刻可以允许多个读线程访问,但是在写线程访问时,所有 ...
- Java中的读写锁
一.读写锁 1.初识读写锁 a)Java中的锁——Lock和synchronized中介绍的ReentrantLock和synchronized基本上都是排它锁,意味着这些锁在同一时刻只允许一个线程进 ...
- go中的读写锁RWMutex
读写锁是针对于读写操作的互斥锁. 基本遵循两大原则: 1.可以随便读.多个goroutin同时读. 2.写的时候,啥都不能干.不能读,也不能写. 解释: 在32位的操作系统中,针对int64类型值的读 ...
- 线程中的读写锁ReadWriteLock
Lock锁还有两个非常强大的类 ReadWriteLock接口实现类ReentrantReadWriteLock(非常重要的锁) 想实现 读取的时候允许多线程并发访问,写入的时候不允许. 这种效果.. ...
- java中的读/写锁
读写锁接口:ReadWriteLock,它的具体实现类为:ReentrantReadWriteLock 使用场景: 对于一个资源,读读能共存,读写不能共存,写写不能共存. 锁降级:从写锁变成读锁: 锁 ...
- 22、Java并发性和多线程-Java中的读/写锁
以下内容转自http://ifeve.com/read-write-locks/: 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些.假设你的程序中涉及到对一些共享资源 ...
- java多线程:并发包中ReentrantReadWriteLock读写锁的锁降级模板
写锁降级为读锁,但读锁不可升级或降级为写锁. 锁降级是为了让当前线程感知到数据的变化. //读写锁 private ReentrantReadWriteLock lock=new ReentrantR ...
随机推荐
- javascript 中的原型继承
javascript圆形变成的基本规则: 所有数据都是对象: 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它: 对象会记住它的原型: 如果对象无法响应某个请求,它会把这个请求委托给 ...
- vi编辑器之删除操作
参见 1.vi列删除 方法一: ctrl+v进入列编辑模式: 将光标定位子想要删除的起始列: 移动光标至结束列(直接通过移动光标选中,对列不对齐时,可能比较长的行,无法全部选中,尤其是需要一直删除到行 ...
- Matlab_spectrogram_短时傅里叶分析_实现与讨论
在语音与音乐处理过程中,常用到短时傅里叶变换(Short Time Fourier Transformation, STFT).在一些学习路径中,STFT也是学习小波之前的预备知识.本文简单实现了 M ...
- postgresql,封装数据库语句时,查询报错。
sql = "select password from admin where username = " + "\'" + username + "\ ...
- 浅谈jquery事件命名空间
什么是jquery的事件命名空间? 先看如下简单代码: $("#btn").on("click.name1.name2",function(){ console ...
- Flask 上下文管理
为什么用threading.local? 我们都知道线程是由进程创建出来的,CPU实际执行的也是线程,那么线程其实是没有自己独有的内存空间的,所有的线程共享进程的资源和空间,共享就会有冲突,对于多线程 ...
- SQLServer 2008R2主从部署实战
说明: 由于临时接到做OA的主从环境,基于Windows 200R2 SQLServer2008 R2,由于搜索的资料都不完整,好多重要之处有遗漏,亲自动手做了好几次,填完了坑,整理以备忘记与分享,如 ...
- 2018-2019-2 网络对抗技术 20165228 Exp5 MSF基础应用
2018-2019-2 网络对抗技术 20165228 Exp5 MSF基础应用 exploit选取 主动攻击:ms17_010_eternalblue(唯一) 浏览器攻击:ms05_054_onlo ...
- Skynet服务热点火焰图分析
最近花了一周时间对场景服务进行热点分析,利用以前的火焰图工具做了一点微小的贡献,分享下心得(仓库地址在https://github.com/spin6lock/skynet_systemtap_set ...
- JAVA日常之一
一.JDK安装及环境变量设置 下载jdk安装包,如jdk-8u65-windows-x64.exe,点击安装,记住安装路径如E:\Program Files\Java\jdk1.8.0_65: 打开环 ...