MongoDB事务
在本页
在MongoDB中,对单个文档的操作是原子的。因为您可以使用嵌入式文档和数组来捕获单个文档结构中的数据之间的关系,而不是在多个文档和集合之间进行规范化,所以这种单文档原子性消除了许多实际用例中对多文档事务的需求。
对于需要原子性地读写多个文档(在单个或多个集合中)的情况,MongoDB支持多文档事务。使用分布式事务,可以跨多个操作,集合,数据库,文档和分片使用事务。
以下示例重点介绍了事务API的关键组成:
- PYTHON
- JAVA (SYNC)
- NODE.JS
- PHP
- MOTOR
- C
- C++11
- C#
该示例使用新的回调API来处理事务,该API启动事务,执行指定的操作并提交(可能因为错误而中止)。新的回调API还针对
TransientTransactionError
或UnknownTransactionCommitResult
提交错误合并了重试逻辑。重点
- 对于MongoDB 4.2(副本集和分片群集)上的事务,客户端必须使用将MongoDB驱动程序更新为MongoDB 4.2。
- 使用驱动程序时,事务中的每个操作必须与会话相关联(即,将每个操作传递在会话中传递)。
参考
分布式事务和多文档事务
从MongoDB 4.2开始,这两个术语是同义词。 分布式事务是指分片群集和副本集上的多文档事务。 从MongoDB 4.2开始,多文档事务(无论是在分片群集或副本集上)也称为分布式事务。
对于需要原子性地读写多个文档(在单个或多个集合中)的情况,MongoDB支持多文档事务:
- 在4.0版中,MongoDB支持副本集上的多文档事务。
- 在版本4.2中,MongoDB引入了分布式事务,它增加了对分片群集上多文档事务的支持,并合并了对副本集上多文档事务的现有支持。
要在MongoDB 4.2部署(副本集和分片群集)上使用事务,客户端必须使用为MongoDB 4.2更新的MongoDB驱动程序。
多文档交易是原子性的(即提供“全有或全无”主张):
- 提交事务时,将保存在事务中进行的所有数据更改,并在事务外部可见。 也就是说,一个事务在回滚其他事务时将不会提交其某些更改。在提交事务之前,在事务外部看不到在事务中进行的数据更改。
但是,当事务写入多个分片时,并非所有外部读取操作都需要等待已提交事务的结果在所有分片上可见。 例如,如果提交了一个事务,并且在分片A上可以看到写1,但是在分片B上却看不到写2,则外部读取时设置读关注
"local"
结果为可以读取写入1的结果而看不到写入2。- 当事务中止时,在事务中进行的所有数据更改都将被丢弃,而不会变得可见。 例如,如果事务中的任何操作失败,则事务中止,并且在事务中进行的所有数据更改都将被丢弃,而不会变得可见。
重点
在大多数情况下,与单文档写入相比,多文档事务产生的性能成本更高,并且多文档事务的可用性不应替代有效的架构设计。 在许多情况下, 非规范化数据模型(嵌入的文档和数组) 仍将是最佳选择您的数据和用例。 也就是说,在许多情况下,适当地对数据建模将最大程度地减少对多文档交易的需求。
分布式事务可用于多个操作,集合,数据库,文档,以及从MongoDB 4.2分片开始的。
对于事务:
- 您无法在
config
,admin
或local
数据库中读取/写入集合。 - 您无法写入
system。*
集合。 - 您无法返回支持的操作的查询计划(如
explain
)。
提示
在事务中执行不同的操作:
- 代替
db.coll.distinct("x")
,使用db.coll.aggregate([{ $group: { _id: null, distinctValues: { $addToSet: "$x" } } },{ $project: { _id: 0 } }]) - 代替
db.coll.distinct("x", { status: "A" })