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

事务中的批量操作

在本指南中,您可以学习如何使用 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(或关联的 MongoDatabaseMongoCollection)一起使用。将 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 MethodsAsynchronous Methods 标签页中进行选择,了解管理事务的方法:

方法
说明

StartTransaction()

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

参数TransactionOptions (可选)

AbortTransaction()

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

参数CancellationToken

CommitTransaction()

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

参数CancellationToken

WithTransaction()

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

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


参数Func <IClientSessionHandle, CancellationToken, Task<TResult>>TransactionOptionsCancellationToken
返回类型Task <TResult>

方法
说明

StartTransaction()

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

参数TransactionOptions (可选)

AbortTransactionAsync()

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

参数CancellationToken
返回类型Task

CommitTransactionAsync()

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

参数CancellationToken
返回类型Task

WithTransactionAsync()

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

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


参数Func <IClientSessionHandle, CancellationToken, Task<TResult>>TransactionOptionsCancellationToken
返回类型Task <TResult>

提示

配置事务

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

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

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

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

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

  4. 将文档插入 booksfilms 集合。

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

var books = database.GetCollection<Book>("books");
var films = database.GetCollection<Film>("films");
// Begins transaction
using (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!");
}
Successfully committed transaction!

注意

不支持并行操作

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

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

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

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