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 ...
随机推荐
- 微信小程序 数据库指引 前端操纵数据库失败
把注释解开后,点击添加显示失败了 看了下注解,发现是数据库权限问题, 修改一下成第一个,然后点击又失败了,多点击几下,就会成功! 哦 别忘了时刻 ctrl +s 保存,如果你习惯了idea 自动保存的 ...
- 阿里云物联网套件(iot)设备间通信(M2M)在web端的实践
之前通过nodejs连接到阿里云物联网mqtt,后又用浏览器连接,总结一下: 由于项目是SPA,使用webpack,关键代码: 同样使用mqtt.js之前先install: npm install - ...
- 微信小程序个人/企业开放服务类目一览表
微信小程序个人/企业开放服务类目一览表 微信小程序个人开放服务类目表 服务类目 类目分类一 类目分类二 引导描述 出行与交通 代驾 / / 生活服务 家政.丽人.摄影/扩印.婚庆服务.环保回收/废 ...
- Springboot框架,实现请求数据解密,响应数据加密的功能。
一.简要说明: 在做这个功能的时候,参考了很多文章,也试了用过滤器解决.但总体来说还是很麻烦,所以换了另一种解决方案.直接实现RequestBodyAdvice和ResponseBodyAdvice两 ...
- fdsafdsafds
name1 = input('请输入一个名字:') name2 = input('请输入一个名字: ') animal = input('请输入一个名字 :') print('刚按完摩的{}出门看见{ ...
- 巧用MYSQL中SQL语句
static bool Verify(string username, string password) { //string strSql = "select * from users w ...
- MySQL_DML语言
#MySQL--DML语言##SQL组成DDL:数据库模式定义语言,关键字:create DML:数据操纵语言,关键字:insert,delete,update DCL:数据库控制语言,关键字:gra ...
- 项目工程中的WebRoot与WebContent有什么区别?
[1] 在MyEclipse中创建web项目后,web程序的根目录文件夹是WebRoot,而创建dynam web project时候,web程序的根 目录文件夹是WebContent,他们之间没有本 ...
- nodejs-- vuex中mapActions
mapActions() 返回的是一个对象, 用了 ... 扩展符后,才可以放进一个对象里,和其他组件内定义的 method 在同一个 methods 对象. { methods: mapAction ...
- 安装FireEye渗透测试套件commando-vm
前两天FireEye开源了套他们自己的渗透测试工具,玩了下,这里简单讲一下我安装的过程. 1.首先是虚拟机,在virtualbox或者vmware中安装一个新的Windows系统,win7或者win1 ...