事务
概述
在本指南中,您可以学习如何使用Rust驱动来执行事务。事务允许您执行一系列操作,只有当整个事务提交时,数据才会改变。如果事务中的任何操作未成功,驱动程序将停止事务并丢弃所有更改,以防止它们在任何可见之前。这个特性称为原子性。
在MongoDB中,事务在逻辑会话中运行。会话是一系列相关的读取或写入操作,您希望按顺序执行。会话使一组操作具有因果一致性,并允许您在符合ACID标准的事务中运行操作,即满足原子性、一致性、隔离性和持久性期望的事务。MongoDB保证事务操作涉及的数据保持一致性,即使操作遇到意外错误。
当使用Rust驱动时,您可以从Client
实例创建一个新的会话为ClientSession
类型。您可以通过重用客户端来提高应用程序的性能,而不是每次都实例化一个新的客户端。
警告
仅在使用创建它的Client
上运行的ClientSession
操作中使用ClientSession
。使用不同Client
的ClientSession
会导致操作错误。
方法
通过在您的Client
实例上调用start_session()
方法来创建一个ClientSession
。然后,您可以使用ClientSession
类型提供的方法修改会话状态。以下表格描述了这些方法
方法 | 描述 |
---|---|
start_transaction() | 在此会话上启动新的事务。必须将会话传递到事务中的每个操作中,否则操作将在事务之外运行。 您可以通过将 TransactionOptions 选项构建器方法链接到start_transaction() 来设置事务选项。在事务中运行的操作返回的错误可能包含一个 TRANSIENT_TRANSACTION_ERROR 标签,这表示整个事务可以被结束,然后可以期望成功的情况下重新尝试。 |
commit_transaction() | 提交此会话的活动事务。如果会话中没有活动事务或事务之前已结束,则此方法返回错误。 此方法可能返回一个包含 UNKNOWN_TRANSACTION_COMMIT_RESULT 标签的错误,这表示无法确定提交的事务是否满足设置的写入关注。如果您遇到此错误,可以安全地重试提交,直到写入关注得到满足或方法返回不带此标签的错误。 |
abort_transaction() | 结束此会话的活动事务。如果会话中没有活动事务或事务已被提交或结束,则此方法返回错误。 |
and_run() | 运行给定的回调,然后提交或结束事务。如果回调抛出一个带有 TRANSIENT_TRANSACTION_ERROR 标签的错误,则驱动程序会重试回调和提交。如果它们抛出任何其他错误,则驱动程序会结束事务并将错误返回给调用者。当您使用此方法执行事务时,驱动程序会自动处理任何错误,因此您可以选择省略错误处理代码。因为回调返回一个未来对象并且可以多次运行,所以 Rust 语言对捕获值的借用规则可能比较严格。因此, and_run() 方法接受一个上下文参数,该参数被传递给回调。参数: 上下文 C ,回调 FnMut(&'a mut ClientSession, &'a mut C) |
重要
可以在事务中运行的方法
要运行 MongoDB 事务中的操作,您必须将 session()
方法链接到操作。此方法接受一个 ClientSession
实例作为参数。
例如,要删除一个文档,您通常可以使用 delete_one()
方法。然而,要在一个事务中删除一个文档,您必须将 session()
方法链接到 delete_one()
并将会话作为参数传递。
示例
以下代码定义了 insert_media()
回调函数,该函数将数据插入到 books
和 films
集合中
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(()) }
以下代码完成以下操作以执行事务
使用
start_session()
方法从客户端创建会话。调用
start_transaction()
方法以启动事务。调用
and_run()
方法在事务中运行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 兼容性的信息,请参阅 MongoDB 网站上的数据库管理系统中 ACID 属性是什么?文章。
要了解更多关于插入操作的信息,请参阅插入文档指南。
API 文档
要了解更多关于本指南中提到的方法和类型,请参阅以下 API 文档