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

事务中的批量操作

在本指南中,您可以学习如何使用 MongoDB .NET/C# 驱动程序来执行事务。事务 允许您运行一系列操作,这些操作在提交事务之前不会更改任何数据。如果事务中的任何操作返回错误,驱动程序就会取消事务,并在所有数据更改变得可见之前予以丢弃。

MongoDB 保证事务操作中涉及的数据保持一致,即使操作遇到意外错误。

在MongoDB中,事务在逻辑会话中运行。会话是您打算按顺序运行的一组相关读取或写入操作。会话启用一群组操作的因果一致性,或者允许您在ACID transaction中执行操作。

使用 .NET/C# 驱动程序时,可以从 MongoClient 实例创建一个新会话,并将其类型定义为 IClientSession。我们建议您将客户端重复用于多个会话和事务,而不是每次都实例化新客户端。

以下示例展示了如何通过调用 StartSession() 方法来创建会话:

var client = new MongoClient("mongodb://localhost:27017");var session = client.StartSession();

警告

仅应将 IClientSession 与创建它的 MongoClient(或关联的 MongoDatabase 或 MongoCollection)一起使用。将 IClientSession 与其他 MongoClient 一起使用会导致操作错误。

您可以通过将 ClientSessionOptions 类的实例传递给 StartSession() 方法来自定义会话行为。下表描述了可以在 ClientSessionOptions对象上设立的属性:

属性
说明

CausalConsistency

指定会话是否具有因果一致性。在具有因果一致性的会话中,驱动程序会按照发出的顺序执行操作。要了解更多信息,请参阅 因果一致性。

数据类型:boolean
默认:true

DefaultTransactionOptions

指定会话的默认事务选项。这包括最大提交时间、读关注(read concern)、读取偏好(read preference)和写关注(write concern)。

数据类型:TransactionOptions
默认:null

Snapshot

指定驱动程序是否执行快照读取。要进一步了解快照读取,请参阅 MongoDB Server 手册中的读关注(read concern)“快照”。

数据类型:boolean
默认值:false

SnapshotTime

指定驱动程序在会话中读取所有数据的集群时间。在设置此属性时,必须将 Snapshot 设置为 true。要了解更多信息,请参阅 MongoDB Server 手册中的 读关注(read concern)“快照”。

数据类型:BsonTimestamp
默认:null

DefaultTransactionOptions属性接受 TransactionOptions 类的实例。下表描述了可以在 TransactionOptions对象上设立的属性:

属性
说明

MaxCommitTime

单个 commitTransaction 命令可以运行的最长时间。如果提交超过此限制,MongoDB Server 将返回 MaxTimeMSExpired 错误,并不提交事务中的更改。出现此错误后,驱动程序不会重试提交。

如果您省略此属性,MongoDB Server 将应用默认事务运行时间限制。

数据类型:TimeSpan?
默认值:null

ReadConcern

会话中每个事务的读关注(read concern)。要了解更多信息,请参阅 MongoDB Server 手册中的读关注(read concern)。

如果省略此属性,则事务使用会话级读关注(read concern)(如果已设置)。如果还省略会话级读关注,则事务使用客户端级读关注(read concern)。

数据类型:ReadConcern
默认:null

ReadPreference

会话中每个事务的读取偏好(read preference)。要了解更多信息,请参阅 MongoDB Server 手册中的读取偏好(read preference)。

如果您省略此属性,则事务将使用会话级别的读取偏好(read preference)(如果您设置了该偏好)。如果您还省略会话级别的读取偏好(read preference),则事务将使用客户端级别的读取偏好(read preference)。

数据类型:ReadPreference
默认:null

WriteConcern

会话中每个事务的写关注(write concern)。要学习更多信息,请参阅 MongoDB Server 手册中的写关注(write concern)。

如果您省略此属性,则事务使用会话级别的写关注(write concern)(如果您设置了会话级别的写关注(write concern))。如果您还省略会话级别的写关注(write concern),则事务使用客户端级别的写关注(write concern)。

数据类型:WriteConcern
默认:null

以下代码示例展示了如何使用自定义选项创建会话:

var client = new MongoClient("mongodb://localhost:27017");var sessionOptions = new ClientSessionOptions{ CausalConsistency = true, DefaultTransactionOptions = new TransactionOptions( readConcern: ReadConcern.Available, writeConcern: WriteConcern.Acknowledged)}; var session = client.StartSession(sessionOptions);

MongoDB在某些客户端会话中实现因果一致性。因果一致性模型ACID 一致性保证在分布式系统中,会话中的操作按因果顺序运行。客户端观察到的结果与因果关系或操作之间的依赖关系一致。示例,如果您执行一系列操作,其中一个操作在逻辑上依赖于另一个操作的结果,则任何后续读取都会反映这种依赖关系。

为了保证因果一致性,客户端端会话必须满足以下要求:

  • 启动会话时,驱动程序必须启用因果一致性选项。该选项默认启用。

  • 操作必须在单个线程的单个会话中运行。否则,会话或线程必须相互传达optime和集群时间值。 要查看传达这些值的两个会话的示例,请参阅MongoDB Server手册中的因果一致性示例。

  • 您必须使用 ReadConcern.Majority读关注(read concern)。

  • 您必须使用 WriteConcern.WMajority写关注(write concern)。这是默认的写关注(write concern)值。

下表描述了因果一致会话提供的ACID 一致性保证:

保证
说明

读取写入操作

读取操作会反映之前写入操作的结果。

单调读取

读取操作不会返回反映比先前读取操作更早的数据状态的结果。

单调写入

如果写入操作必须先于其他写入操作,则服务器会先运行此写入操作。

示例,如果调用 InsertOne() 插入文档,然后调用 UpdateOne() 修改插入的文档,则服务器首先运行插入操作。

读取后写入

如果写入操作必须在其他读取操作之后执行,服务器会先执行读取操作。

示例,如果您调用 Find() 来检索文档,然后调用 DeleteOne() 来删除检索到的文档,则服务器会先运行查找操作。

提示

要学习;了解有关本节中提到的概念的更多信息,请参阅以下MongoDB Server手册条目:

在 MongoClient 实例上使用同步 StartSession() 或异步 StartSessionAsync() 方法创建 IClientSession。然后,您可以使用 IClientSession 接口提供的方法集来修改会话状态。从以下 Synchronous Methods 和 Asynchronous Methods 标签页中进行选择,了解管理事务的方法:

方法
说明

StartTransaction()

在该会话上启动使用给定选项配置的新事务。如果会话已存在正在进行的事务,则抛出异常。要了解有关该方法的更多信息,请参阅服务器手册中的startTransaction() 页面。

参数:TransactionOptions (可选)

AbortTransaction()

终止此会话的活动事务。如果会话没有活动事务,或事务已提交或结束,则抛出异常。要了解有关此方法的更多信息,请参阅服务器手册中的 abortTransaction() 页面。

参数:CancellationToken

CommitTransaction()

提交此会话的活动事务。如果此会话没有活动事务或事务已结束,则抛出异常。要了解有关此方法的更多信息,请参阅服务器手册中的 commitTransaction() 页面。

参数:CancellationToken

WithTransaction()

在此会话上启动事务并运行给定的回调。要了解有关此方法的更多信息,请参阅服务器手册中的 withTransaction() 页面。

重要提示:在 WithTransaction()使用的回调函数中捕获异常时,必须在退出 try-catch区块之前重新抛出异常。否则可能会导致无限循环。 有关如何处理这种情况下的异常的更多详细信息,请参阅《服务器》手册中的“事务”,并从语言下拉列表中选择 C#以查看示例。


参数:Func <IClientSessionHandle, CancellationToken, Task<TResult>>、TransactionOptions、CancellationToken
返回类型:Task <TResult>

提示

配置事务

您可以通过将 TransactionOptions 类的实例传递给 StartTransaction() 或 WithTransaction() 方法来自定义单个事务的行为。您在此处设立的选项会覆盖您在 ClientSessionOptions对象上设立的默认ACID 事务选项。

此示例展示了如何通过以下步骤创建会话、创建事务以及将文档插入到事务中的多个集合中:

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

  2. 创建 TransactionOptions对象以配置ACID 事务。

  3. 使用 StartTransaction() 方法启动事务。

  4. 将文档插入 books 和 films 集合。

  5. 使用 CommitTransaction() 方法提交事务。

var books = database.GetCollection<Book>("books");var films = database.GetCollection<Film>("films"); // Begins transactionusing (var session = mongoClient.StartSession()){ // Configures transaction options var transactionOptions = new TransactionOptions( readConcern: ReadConcern.Majority, writeConcern: WriteConcern.WMajority ); session.StartTransaction(transactionOptions); try { // Creates sample data var book = new Book { Title = "Beloved", Author = "Toni Morrison", InStock = true }; var film = new Film { Title = "Star Wars", Director = "George Lucas", InStock = true }; // Inserts sample data books.InsertOne(session, book); films.InsertOne(session, film); // Commits our transaction session.CommitTransaction(); } catch (Exception e) { Console.WriteLine("Error writing to MongoDB: " + e.Message); return; } // Prints a success message if no error thrown Console.WriteLine("Successfully committed transaction!");}

注意

不支持并行操作

.NET/ C#驱动程序不支持在单个ACID 事务中运行并行操作。

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

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

要进一步了解本指南所讨论的任何类型或方法,请参阅以下 API 文档: