登 录
注 册
< 数 据 库
MySQL
ClickHouse
ES
Doris
MongoDB
Redis
其他DB
重新定义OLTP数据库
MongoDB基本操作
复制集机制及原理
MongoDB事务
热门推荐>>>
中台架构
中台建设与架构
Hadoop
源码分析-NN启动(三)
HBase
HBased对接Hive
Linux
Nginx高可用
Python
数据导出工具
Flink
3分钟搭建Flink SQL测试环境
Kafka
Kafka对接Flume
深度学习
卷积神经网络
数据结构与算法
选择合适的算法
MySQL
数据备份恢复
计算机系统
信号量同步线程
Hive
Hive调优参数大全
其他框架
Azkaban Flow1.0与2.0
ClickHouse
表引擎-其他类型
技术成长
最好的职业建议
精选书单
技术成长书单—机器学习
技术资讯
数据在线:计算将成为公共服务
开发工具
IntelliJ IDEA 20年发展回顾(二)
系统工具
Mac命令行工具
虚拟化
内存虚拟化概述
云原生
云原生构建现代化应用
云服务
一文搞懂公有云、私有云...
Java
Spring Boot依赖注入与Runners
Go
Go函数与方法
SQL
SQL模板
当前位置:
首页
>>
MongoDB
>>
MongoDB事务
MongoDB事务
2023-09-10 16:20:31 星期日 发表于北京 阅读:563
![](/static/images/article_images/1694333784.149434.jpeg) 在MongoDB中,对单个文档的操作是原子的。由于可以在单个文档结构中使用内嵌文档和数组来获得数据之间的关系,而不必跨多个文档和集合进行范式化,所以这种单文档原子性避免了许多实际场景中对多文档事务的需求。 对于那些需要对多个文档(在单个或多个集合中)进行原子性读写的场景,MongoDB支持多文档事务。而使用分布式事务,事务可以跨多个操作、集合、数据库、文档和分片使用。 #### 写操作事务 WriteConcern参数的使用 writeConcern决定一个写操作落到多少个节点上才算成功,writeConcern的取值包括: >0:发起写操作,不关心是否成功 1 ~ 集群最大数据节点数:写操作需要被复制到指定节点数才算成功 majority:写操作需要被复制到大多数节点上才算成功 all:全部节点确认收到后才算成功 发起写操作的程序将阻塞到写操作达到指定的节点数为止 针对某个集合设置WriteConcern参数 ``` // 往test集合插入一条数据,并设置3个节点收到数据后才算成功。 // 如果超过3秒还没有同步完,则放弃本次同步 mongo> db.test.insert({name:"shenlibin"}, {writeCoucern:{w:3, wtimeout:3000}}) // 设置某个从节点的数据同步延迟为10秒,也就是数据插入主节点后经过10秒才复制到该节点 mongo> conf.members[2].slaveDelay=10 ``` #### 读操作事务 在读取数据的过程中,我们需要关注以下两个问题: 从哪里读?(关注数据节点位置,由参数readPreference决定) 什么样的数据可以读?(关注数据的隔离性,由参数readConcern参数决定) ##### 1、readPreference参数 参数可选值 该参数决定使用哪一个节点来满足正在发起的读请求,可选的值包括: >primary:只选择主节点(默认值) primaryPreferred:优先选择主节点,如果不可用则选择从节点 secondary:只选择从节点 secondaryPreferred:优先选择从节点,如果从节点不可用,则可选择主节点 nearest:选择最近的节点,(客户端ping MongoDB的服务器,延迟最小的则视为最近) readPreference配置的几种方法 通过MongoDB的连接串参数 `mongodb://host1:27107,host3:27107,host3:27107/?replicaSet=rs&readPreference=secondary` 通过MongoDB驱动程序API `MongoCollection.withReadPreference(ReadPreference readPref)` 通过MongoDB Shell指定本次查询从从节点上面读 `db.collection.find({}).readPref("secondary)` ##### 2、readConcern参数 在readPreference参数选择了 从哪台节点读取数据之后,readConcern参数决定了这个节点上的数据哪些是可读的,类似于关系数据库中的隔离级别。 参数可选值 >available:读取所有可用的数据,有可能会读取到不是当前分片的数据(因为分片数据还没有完全复制到当前节点) local(MongoDB默认参数):读取所有可用且属于当前分片的数据; majority:读取在大多数节点上提交完成的数据; linearizable:可线性化读取文档;安全级别比majority更高,主要是防止某台机器与集群断开,导致客户端从该机器上读取的数据不是最新数据的场景 snapshot:读取最近快照中的数据,属于最高安全级别 注意事项 >虽然看上去总是应该选择local,但毕竟对结果集进行过滤会造成额外的开销,在一些无关紧要的场景(比如统计)下,也可以考虑available MongoDB <=3.6不支持从节点使用{readConcern: "local"} 从主节点读取数据时默认readConcern是local,从从节点读取数据时默认readConcern是available(向前兼容原因) #### 实现安全的读写分离 -------------------------------------------------------------------------------- 读写分离需要面对的难题:在主节点写入,从节点因为网络延迟没有及时返回数据; 一种可行的方案是: 写:写入的时候指定写入到大多数节点才视为本次写入成功(通过writeConcern参数控制) `db.test.insert({oid: 101, sku: "12345", q: 1}, {writeConcern: {w: "majority"}})` 读:读取的时候指定只读取多数节点上有的数据(通过readConcern参数控制) `db.test.find({oid:101}).readPref("secondary").readConcern("majority")` #### MongoDB事务注意事项 -------------------------------------------------------------------------------- 1、可以实现和关系型数据库类似的事务场景,但是能不用尽量不要用 2、必须使用与MongoDB4.2兼容的驱动; 3、事务默认必须在60秒内完成(可调),否则将被取消; 4、涉及事务的分片不能使用仲裁节点; 5、事务会影响chunk迁移效率,正在迁移的chunk也可能造成事务提交失败(重试即可); 6、多文档事务中的读操作必须使用主节点读; 7、readConcern只应该在事务级别设置,不能设置在每次读写操作上。