原子性保证:All write operations in MongoDB are atomic on the level of a single document.
批量写,bulkwrite语法:针对同一个集合多个cud操作。不支持类似mysql的事务。无回滚。默认按顺序执行,出错返回未执行的操作。可以指定无序批量,mongo会并行执行,出错不会终止执行。 bulkWrite() supports the following write operations: insertOne updateOne updateMany replaceOne deleteOne deleteMany
持久化:写有同步与异步模式。通过参数调整在持久化与性能之间平衡。
{ w: <value>, j: <boolean>, wtimeout: <number> } w:majority:写请求已被传播到多数节点,(含主节点)才确认。日志是否已持久化看参数j
j:true w指定数量节点或多数节点日志已持久化才确认。
读和写模式密切相关。写日志持久化与否影像到读的一致性。当j:false时,日志并未持久化到硬盘,只是在内存中,所以此时failover都有可能出现读不一致。
读:readPreference控制从复制集的哪个节点读取数据,这个特性可方便的实现读写分离、就近读取等策略。默认primiry。
readConcern 用来控制读一致性,用户可以在性能和一致性之间取舍
The readConcern
option is available for the following operations:
-
find
commandaggregate
command and thedb.collection.aggregate()
methoddistinct
commandcount
commandparallelCollectionScan
commandgeoNear
commandgeoSearch
command
为简化讨论,下面讨论基于w:majority,j:true,readPreference:primiry
常见场景:遍历find返回的cursor。
-
- local 默认,总是读取最新的数据,表明客户端可以看到还未被持久化的数据。集群环境下,可能只有primiry完成写,而不是多数节点完成。这时primiry failover后再上线会回滚数据。(会出现读未提交。)
- majority 返回已被多数节点写成功的数据。注意多数确认写成功可能不是最新的(因为最新的可能只有primiry成功了,而不是多数成功)。(隔离并发的未提交写)
- linearizable ,返回已被多数节点确认为写成功,且早于本次读之前修改的数据(所有并发写都被隔离)。
- mysql 提供多语句打包事务语法(begin,commit)事务是并行的,通过隔离级别来提供一致性,提供行锁来保证资源不会被并发修改。
- redis提供多语句打包事务语法(multi,exec)事务是串行执行的,不会并发修改,不提供锁,但是通过watch机制保证在事务执行前资源被修改终止当前事务执行。另外因为串行事务的隔离界别,不会有并发修改。
- mongo 无多语句事务语法。另外单条update涉及多文档时也非原子执行。find涉及多文档时可以通过
readConcern进行并发修改隔离。
不支持mysql中常见的多表多行的事务,也不支持单表多行事务,其批量语法可能部分成功,只能使用补偿机制,达到最终一致性。 - mongo针对update涉及多文档时,提供的
$isolated可以保证update多文档不会有并发访问。但是不提供回滚。(不支持分片集群。)
- mongo的 two-phase commits 提供transaction-like semantics.
- mongo建议使用唯一索引和版本控制并发。这在mysql中也很常见。
时间: 2024-11-05 22:05:24