Overview
在本指南中,您可以学习如何使用 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
您可以通过将 ClientSessionOptions 类的实例传递给 StartSession() 方法来自定义会话行为。下表描述了可以在 ClientSessionOptions对象上设立的属性:
属性 | 说明 |
|---|---|
| |
| 指定会话的默认ACID 事务选项。这包括最大提交时间、读关注(read concern)、读取偏好(read preference)和写关注(write |
| |
| 指定驾驶员读取会话中所有数据的集群时间。设置此属性时,必须将 |
DefaultTransactionOptions属性接受 TransactionOptions 类的实例。下表描述了可以在 TransactionOptions对象上设立的属性:
属性 | 说明 |
|---|---|
| |
| 会话中每个ACID 事务的读关注。要学习;了解更多信息,请参阅MongoDB Server手册中的读关注。如果省略此属性,则事务将使用会话级读关注(read |
| 会话中每个ACID 事务的读取偏好。要学习;了解更多信息,请参阅MongoDB Server手册中的读取偏好。如果省略此属性,则事务将使用会话级读取偏好(read |
| 为会话中的每个ACID 事务写入关注。要学习;了解更多信息,请参阅MongoDB Server手册中的写关注。如果省略此属性,则事务将使用会话级写关注(write |
以下代码示例展示了如何使用自定义选项创建会话:
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);
因果一致性(Causal Consistency)
MongoDB在某些客户端会话中实现因果一致性。因果一致性模型ACID 一致性保证在分布式系统中,会话中的操作按因果顺序运行。客户端观察到的结果与因果关系或操作之间的依赖关系一致。示例,如果您执行一系列操作,其中一个操作在逻辑上依赖于另一个操作的结果,则任何后续读取都会反映这种依赖关系。
为了保证因果一致性,客户端端会话必须满足以下要求:
启动会话时,驱动程序必须启用因果一致性选项。该选项默认启用。
操作必须在单个线程的单个会话中运行。否则,会话或线程必须相互传达optime和集群时间值。 要查看传达这些值的两个会话的示例,请参阅MongoDB Server手册中的因果一致性示例。
您必须使用
ReadConcern.Majority读关注(read concern)。您必须使用
WriteConcern.WMajority写关注(write concern)。这是默认的写关注(write concern)值。
下表描述了因果一致会话提供的ACID 一致性保证:
保证 | 说明 |
|---|---|
读取写入操作 | 读取操作会反映之前写入操作的结果。 |
单调读取 | 读取操作不会返回反映比先前读取操作更早的数据状态的结果。 |
单调写入 | 如果写入操作必须先于其他写入操作,则服务器会先运行此写入操作。 示例,如果调用 |
读取后写入 | 如果写入操作必须在其他读取操作之后执行,服务器会先执行读取操作。 示例,如果您调用 |
提示
要学习;了解有关本节中提到的概念的更多信息,请参阅以下MongoDB Server手册条目:
方法
在 MongoClient 实例上使用同步 StartSession() 或异步 StartSessionAsync() 方法创建 IClientSession。然后,您可以使用 IClientSession 接口提供的方法集来修改会话状态。从以下 Synchronous Methods 和 Asynchronous Methods 标签页中进行选择,了解管理事务的方法:
方法 | 说明 |
|---|---|
| 在此会话上启动使用给定选项配置的新ACID 事务。如果会话已存在正在进行的ACID 事务,则会引发异常。要学习;了解有关此方法的更多信息,请参阅服务器手册中的 startTransaction() 页面。参数: |
| 结束此会话的ACID 事务。如果会话没有ACID 事务或者ACID 事务已提交或结束,则会引发异常。要学习;了解有关此方法的更多信息,请参阅服务器手册中的 abortTransaction() 页面。参数: |
| 提交此会话的ACID 事务。如果会话没有ACID 事务或ACID 事务已结束,则会引发异常。要学习;了解有关此方法的更多信息,请参阅服务器手册中的 commitTransaction() |
| 在此会话上启动事务并运行给定的回调。要了解有关此方法的更多信息,请参阅服务器手册中的 withTransaction() 页面。 重要提示:在
|
方法 | 说明 |
|---|---|
| 在此会话上启动使用给定选项配置的新ACID 事务。如果会话已存在正在进行的ACID 事务,则会引发异常。要学习;了解有关此方法的更多信息,请参阅服务器手册中的 startTransaction() 页面。参数: |
| 结束此会话的ACID 事务。如果会话没有ACID 事务或者ACID 事务已提交或结束,则会引发异常。要学习;了解有关此方法的更多信息,请参阅服务器手册中的 abortTransaction() 页面。参数: |
| 提交此会话的ACID 事务。如果会话没有ACID 事务或ACID 事务已结束,则会引发异常。要学习;了解有关此方法的更多信息,请参阅服务器手册中的 commitTransaction() |
| 在此会话上启动事务并运行给定的回调。要了解有关此方法的更多信息,请参阅服务器手册中的 withTransaction() 页面。 重要提示:在
|
提示
配置事务
您可以通过将 TransactionOptions 类的实例传递给 StartTransaction() 或 WithTransaction() 方法来自定义单个事务的行为。您在此处设立的选项会覆盖您在 ClientSessionOptions对象上设立的默认ACID 事务选项。
例子
此示例展示了如何通过以下步骤创建会话、创建事务以及将文档插入到事务中的多个集合中:
使用
StartSession()方法从客户端创建会话。创建
TransactionOptions对象以配置ACID 事务。使用
StartTransaction()方法启动事务。将文档插入
books和films集合。使用
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 文档
要进一步了解本指南所讨论的任何类型或方法,请参阅以下 API 文档: