对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Docs 菜单

事务

在本指南中,您可以了解如何使用 Rust 驱动程序执行事务。事务允许您执行一系列操作,这些操作仅在整个事务提交后才会更改数据。如果事务中的任何操作不成功,驱动程序就会停止事务,并在所有数据更改变得可见之前予以丢弃。这种特征称为原子性

在 MongoDB 中,事务在逻辑会话中运行。 会话是要按顺序运行的一组相关读取或写入操作。 会话为一组操作启用因果一致性,并允许您在符合 ACID 的事务中运行操作,这是一个满足原子性、一致性、隔离性和持久性预期的事务。 MongoDB 保证事务操作中涉及的数据保持一致,即使操作遇到意外错误。

使用 Rust 驱动程序时,您可以从Client实例创建一个新会话,并将其类型定义为ClientSession 。 您可以将客户端重复用于多个会话和事务,而不是每次都实例化新客户端,从而提高应用程序的性能。

警告

仅在创建ClientSessionClient上运行的操作中使用 。 将ClientSession与不同的Client一起使用会导致操作错误。

Client实例上使用start_session()方法创建ClientSession 。 然后,您可以使用ClientSession类型提供的方法修改会话状态。 下表描述了这些方法:

方法
说明

start_transaction()

在此会话上启动新事务。必须将会话传递到事务中的每个操作,否则操作将在事务外运行。

您可以通过将 TransactionOptions 选项构建器方法链接到 start_transaction() 来设置事务选项。

在事务内运行的操作返回的错误可能包含 TRANSIENT_TRANSACTION_ERROR 标签,这表示可以结束整个事务,然后重试,并预计将会成功。

commit_transaction()

提交此会话的活动事务。如果此会话没有活动事务或事务已结束,则此方法返回错误。

此方法可能会返回包含 UNKNOWN_TRANSACTION_COMMIT_RESULT 标签的错误,这表示承诺的事务是否满足所设置的写关注(write concern)是未知的。如果遇到此错误,可以安全地重试承诺,直到满足写关注(write concern)或方法返回没有标签的错误。

abort_transaction()

结束此会话的活动事务。 如果该会话没有活动事务或者事务已提交或结束,则此方法将返回错误。

and_run()

运行给定的回调,然后提交或结束事务。驱动程序会重试回调和提交,这些回调和提交会产生带有 TRANSIENT_TRANSACTION_ERROR 标签的错误。如果它们产生任何其他错误,驱动程序将结束事务并将错误返回给调用者。当使用此方法执行事务时,驱动程序会自动处理任何错误,因此您可以选择省略错误处理代码。

由于回调返回未来并可以运行多次,因此 Rust 语言闭包借用捕获值的规则可能会受到限制。因此,and_run() 方法接受一个传递给回调的上下文参数。

参数:上下文 C、回调 FnMut(&'a mut ClientSession, &'a mut C)

重要

可在事务中运行的方法

要在事务中运行MongoDB操作,必须将session()方法链接到该操作。 此方法接受ClientSession实例作为参数。

示例,要删除文档,通常可以使用delete_one()方法。 但是,要删除ACID 事务中的文档,您必须将session()方法链接到delete_one()并将会话作为参数传递。

以下代码定义了将数据插入到booksfilmscollection的insert_media()回调:

async fn insert_media(session: &mut ClientSession) -> Result<(), Error> {
let books_coll = session
.client()
.database("db")
.collection::<Document>("books");
let films_coll = session
.client()
.database("db")
.collection::<Document>("films");
books_coll
.insert_one(doc! {
"name": "Sula",
"author": "Toni Morrison"
})
.session(&mut *session)
.await?;
films_coll
.insert_one(doc! {
"name": "Nostalgia",
"year": 1983
})
.session(&mut *session)
.await?;
Ok(())
}

以下代码完成以下操作以执行事务:

  1. 使用start_session()方法从客户端创建会话。

  2. 调用start_transaction()方法启动ACID 事务。

  3. 调用and_run()方法以在ACID 事务中运行insert_media()回调函数。

let mut session = client.start_session().await?;
session
.start_transaction()
.and_run((), |session, _| insert_media(session).boxed())
.await?;
println!("Successfully committed transaction!");
Successfully committed transaction!

如果您需要对事务进行更多控制,请参阅 ClientSession API文档 以查找示例如何手动创建和提交ACID 事务的示例。

注意

不支持并行操作

Rust驱动程序不支持在单个事务中运行并行操作。

如果您使用的是MongoDB Server v8.0 或更高版本,则可以使用批量写入在单个ACID 事务中对多个命名空间执行写入操作。 有关更多信息,请参阅批量操作指南。

要了解有关本指南中提到的概念的更多信息,请参阅服务器手册中的以下页面:

要学习;了解有关ACID compliance的更多信息,请参阅什么是数据库管理系统中的ACID属性? MongoDB网站上的文章。

要了解有关插入操作的更多信息,请参阅插入文档指南。

要进一步了解本指南所提及的方法和类型,请参阅以下 API 文档: