mongodb单文档的操作是原子性的,所以可以将关联的数据存在一份文档里,而不是放在不同的文档,这种方式可以应对大多数多文档原子操作的场景。
对于要读写多文档的原子性,mongodb 提供了事务。基于分布式事务,mongodb 可以提供跨数据集、db、文档和分片的原子性
事务api详见:Transactions API
事务与原子性
分布式事务与多文档的事务
mongodb4.2 开始,两者含义相同。分布式事务是跨分片和副本的的事务
- 4.0开始支持跨副本的事务
- 4.2开始支持跨分片和副本的事务
多数情况下,多文档事务的性能比单文档操作要好。但多文档事务不该是良好设计的替代品。所以应该尽量将关联的数据存放到一份文档中。
事务与操作
涉及数据库目录的操作,例如创建、丢弃数据集、索引,在事务中不允许。事务中不能有可能需要创建一个数据集的插入操作。
更多详见:Transactions and Operations Reference
Count 操作
在事务中使用count,可用 $count 聚合或者
$group 聚合
Distinct 操作
- 没有被分片的数据集,可用
db.collection.distinct()
/distinct 或者聚合流水线
$group
. - 被分片的数据集不能用
db.collection.distinct()
/distinct,要用聚合流水线
$group
事务与会话(session)
- 事务与会话绑定
- 任意时刻一个会话最多只能开启一个事务
- 打开事务的会话中断时,事务被丢弃
Read Concern/Write Concern/Read Preference
以上三个代表应该是mongodb 事务中的读写策略
Read Preference
事务中的操作使用事务级别的 read preference.
使用drivers 可以在事务开始前设置 read preference.
- 若事务级别 read preference 策略未设置, 事务使用会话级别(session-level) read preference.
- 若事务级别和会话级别的 read preference 未设置, 事务采用 客户端级别的 read preference. 默认的客户端级别 read preference 是
primary
.
包含读操作的多文档事务必须使用 primary, 该事务中所有操作都要路由到同一个member
Read Concern
事务中的操作使用事务级别的 read concern ,忽略在数据集级别和db级别设置的 read concern
可在事务开始前设置事务级别的 read concern
- 若事务级别的 read concern未设置 ,事务级别的 read concern 默认使用 会话级别 read concern.
- 若事务级别和会话级别的 read concern 未设置, 事务级别的 read concern 默认为 客户端级别 (client-level) read concern. 客户端级别的 read concern 默认是
"local"
。详见: Transactions and Read Preference.
事务支持以下级别的 read concern
"local"
- 返回节点最近的数据,但可能会被回滚
- 分片集群的事务,
"local"
read concern 不保证数据数据来自同一个snapshot view. 若需要snapshot isolation, 建议使用 "snapshot" read concern.
"majority"
- 若事务用 write concern “majority” 提交,Read concern
"majority"
返回已被副本中大多数节点接受的数据(不能被回滚). - 若事务不用 write concern “majority” 提交,
"majority"
read concern 不保证读取到大多数节点提交的数据. - 对于分片集群的事务,
"majority"
read concern 不保证数据来自分片间的同一个 snapshot view 。若需要snapshot isolation, 建议使用 "snapshot" read concern.
"snapshot"
- 若事务用 write concern “majority” 提交,Read concern
"snapshot"
返回大多数副本接受的数据的snapshot. - 若事务不用 write concern “majority” 提交,
"snapshot"
read concern 不保证读取到大多数节点提交的数据的snapshot. - 对于分片集群的事务, 数据的
"snapshot"
view 在分片中是同步的.
Write Concern
事务使用事务级别的 write concern来提交写操作. 事务中的写操作必须在不显示指定 write concern 下执行,使用默认值. 提交时,写操作用 事务级别 write concern.
可以在事务开始前设置事务级别的 write concern
- 若事务级别的 write concern 未设置 , 提交时,事务级别 write concern 默认为 会话级别 write concern .
- 若事务级别 write concern 和会话级别 write concern 未设置 ,事务级别 write concern 默认为客户端级别 write concern. 默认情况下 客户端级别 write concern 是
w: 1
.
w: 1
Write concern 是 w: 1 时,在主副本(primary)提交后就返回ack
用 w: 1 提交时,事务可能会被回滚
- 用
w: 1
write concern 提交时, 事务级别"majority"
read concern 不保证读到的是多数节点接受的数据. - 用
w: 1
write concern 提交时, 事务级别"snapshot"
read concern 不保证读取的是多数节点接受的数据的snapshot.
w: "majority"
- Write concern
w: "majority"
在多数节点提交后才返回ack (已被主节点和M-1个从节点接受). - 用
w: "majority"
write concern 提交时, 事务级别"majority"
read concern 保证 读取到的是多数节点接受的数据. 对分片集群的事务, 这部分多数提交的数据在分片之间不同步. - 用
w: "majority"
write concern 提交时, 事务级别"snapshot"
read concern 保证读取到的是多数节点接受的且完成同步后的数据
更多事务使用参考: Production Considerations
分片集群的事务参考:Production Considerations (Sharded Clusters)
仲裁者 Arbiters
跨分片的事务中的写操作,若有其他事务向包含仲裁者的分片中读取或写入时,可能会失败回滚
关于事务更多参考:
- Drivers API
- Production Considerations
- Production Considerations (Sharded Clusters)
- Transactions and Operations
转自:https://docs.mongodb.com/manual/core/transactions/
.