Overview概述
In this guide, you can learn how to use the Node.js driver to perform transactions. Transactions allow you to run a series of operations that do not change any data until the entire transaction is committed. If any operation in the transaction fails, the driver ends the transaction and discards all data changes before they ever become visible. This feature is called atomicity.在本指南中,您可以学习如何使用Node.js驱动程序执行事务。事务允许您运行一系列操作,这些操作在提交整个事务之前不会更改任何数据。如果事务中的任何操作失败,驱动程序将结束事务,并在所有数据更改可见之前将其丢弃。这个特性被称为原子性。
Since all write operations on a single document in MongoDB are atomic, you might want to use transactions to make an atomic change that modifies multiple documents. This situation requires a multi-document transaction. 由于MongoDB中单个文档上的所有写入操作都是原子性的,因此您可能希望使用事务进行修改多个文档的原子性更改。这种情况需要多文档事务处理。Multi-document transactions are ACID compliant because MongoDB guarantees that the data involved in your transaction operations remains consistent, even if the driver encounters unexpected errors.多文档事务符合ACID标准,因为MongoDB保证事务操作中涉及的数据保持一致,即使驱动程序遇到意外错误。
To learn more about ACID compliance and transactions, see our article on ACID transactions.要了解更多关于ACID合规性和事务的信息,请参阅我们关于ACID事务的文章。
Note
To execute a multi-document transaction, you must be connected to a deployment running MongoDB Server version 4.0 or later.要执行多文档事务,您必须连接到运行MongoDB Server 4.0或更高版本的部署。
For a detailed list of limitations, see the Transactions and Operations section in the Server manual.有关限制的详细列表,请参阅服务器手册中的事务和操作部分。
Learn more about how to use the driver to perform multi-document transactions in the following sections of this guide:在本指南的以下部分中了解有关如何使用驱动程序执行多文档事务的更多信息:
Causal Consistency因果一致性
MongoDB enables causal consistency in certain client sessions. The causal consistency model guarantees that in a distributed system, operations within a session run in a causal order. MongoDB在某些客户端会话中实现了因果一致性。因果一致性模型保证在分布式系统中,会话内的操作按照因果顺序运行。Clients observe results that are consistent with the causal relationships, or the dependencies between operations. 客户观察到的结果与因果关系或操作之间的依赖关系一致。For example, if you perform a series of operations where one operation logically depends on the result of another, any subsequent reads reflect the dependent relationship.例如,如果执行一系列操作,其中一个操作在逻辑上依赖于另一个操作的结果,则任何后续读取都会反映依赖关系。
To guarantee causal consistency, client sessions must fulfill the following requirements:为保证因果一致性,客户会话必须满足以下要求:
When starting a session, the driver must enable the causal consistency option. This option is enabled by default.开始会话时,驾驶员必须启用因果一致性选项。默认情况下启用此选项。Operations must run in a single session on a single thread. Otherwise, the sessions or threads must communicate the operation time and cluster time values to each other.操作必须在单个线程上的单个会话中运行。否则,会话或线程必须相互传递操作时间和集群时间值。To view an example of two sessions that communicate these values, see the Causal Consistency examples in the MongoDB Server manual.要查看传达这些值的两个会话的示例,请参阅MongoDB服务器手册中的因果一致性示例。You must use a你必须使用majorityread concern.majority读取关注。You must use a你必须使用majoritywrite concern. This is the default write concern value.majority写入关注。这是默认的写入关注值。
The following table describes the guarantees that causally consistent sessions provide:下表描述了因果一致会话提供的保证:
| |
|
Tip
To learn more about the concepts mentioned in this section, see the following MongoDB Server manual entries:要了解有关本节中提到的概念的更多信息,请参阅以下MongoDB Server手册条目:
Transaction APIs事务API
The driver provides two APIs for performing transactions, the Core API and the Convenient Transaction API.驱动程序提供了两个用于执行事务的API,即核心API和方便事务API。
The Core API is a framework that enables you to create, commit, and end transactions. When using this API, you must explicitly perform the following actions:核心API是一个框架,使您能够创建、提交和结束事务。使用此API时,必须明确执行以下操作:
Create, commit, and end the transaction.创建、提交和结束事务。Create and end the session in which you run the transaction.创建并结束运行事务的会话。Implement error-handling logic.实现错误处理逻辑。
The Convenient Transaction API is a framework that enables you to perform transactions without being responsible for committing or ending them. 便捷事务API是一个框架,使您能够执行事务,而无需负责提交或结束事务。This API automatically incorporates error-handling logic to retry operations when the server raises certain error types. To learn more about this behavior, see the Transaction Errors section of this guide.当服务器引发某些错误类型时,此API自动包含错误处理逻辑以重试操作。要了解有关此行为的更多信息,请参阅本指南的“事务错误”部分。
Important
When you connect to MongoDB Server version 4.2 or earlier, you can perform write operations in a transaction only on collections that already exist. When you connect to MongoDB Server version 4.4 and later, the server automatically creates collections as necessary when you perform write operations in a transaction. 当您连接到MongoDB Server 4.2或更早版本时,您只能在已经存在的集合上执行事务中的写入操作。当您连接到MongoDB Server 4.4版及更高版本时,当您在事务中执行写入操作时,服务器会根据需要自动创建集合。To learn more about this behavior, see Create Collections and Indexes in a Transaction in the Server manual.要了解有关此行为的更多信息,请参阅服务器手册中的“在事务中创建集合和索引”。
Core API核心api
The Core API provides the following methods to implement transactions:核心API提供以下方法来实现事务:
startSession()
: creates a new:创建新的ClientSessioninstanceClientSession实例- startTransaction()
: starts a new transaction:启动新事务 - commitTransaction()
: commits the active transaction in the session that it was created in:在创建活动事务的会话中提交该事务 - abortTransaction()
: ends the active transaction in the session that it was created in:结束创建会话中的活动事务 - endSession()
: ends the active session:结束活动会话
You must perform the following steps when using this API:使用此API时,必须执行以下步骤:
Pass the session instance to each operation that you want to run in that session.将会话实例传递给要在该会话中运行的每个操作。Implement a实现一个catchblock in which you identify server transaction errors and implement error-handling logic.catch块,在其中识别服务器事务错误并实现错误处理逻辑。
The following code demonstrates how to perform a transaction by using the Core API:以下代码演示了如何使用Core API执行事务:
async function coreTest(client) {
const session = client.startSession();
try {
session.startTransaction();
const savingsColl = client.db("bank").collection("savings_accounts");
await savingsColl.findOneAndUpdate(
{account_id: "9876"},
{$inc: {amount: -100 }},
{ session });
const checkingColl = client.db("bank").collection("checking_accounts");
await checkingColl.findOneAndUpdate(
{account_id: "9876"},
{$inc: {amount: 100 }},
{ session });
// ... perform other operations执行其他操作
await session.commitTransaction();
console.log("Transaction committed.");
} catch (error) {
console.log("An error occurred during the transaction:" + error);
await session.abortTransaction();
} finally {
await session.endSession();
}
}
Important
Use a Session with the Client That Started It与启动会话的客户端一起使用会话
The driver throws an error if you provide a session from one 如果您提供从一个MongoClient instance to a different client instance.MongoClient实例到另一个客户端实例的会话,驱动程序会抛出错误。
For example, the following code generates an 例如,以下代码生成了MongoInvalidArgumentError error because it creates a ClientSession instance from the client1 client, but provides this session to the client2 client for a write operation:MongoInvalidArgumentError错误,因为它从client1客户端创建了ClientSession实例,但将此会话提供给client2客户端进行写入操作:
const session = client1.startSession();
client2.db('myDB').collection('myColl').insertOne({ name: 'Jane Eyre' }, { session });Tip
Explicit Resource Management显式资源管理
The Node.js driver natively supports explicit resource management for Node.js驱动程序原生支持MongoClient, ClientSession, ChangeStreams, and cursors. This feature is experimental and subject to change. MongoClient、ClientSession、ChangeStreams和游标的显式资源管理。此功能是实验性的,可能会发生变化。To learn how to use explicit resource management, see the v6.9 Release Notes.要了解如何使用显式资源管理,请参阅v6.9发行说明。
To see a fully runnable example that uses this API, see the Use the Core API usage example.要查看使用此API的完全可运行的示例,请参阅使用核心API使用示例。
Convenient Transaction API便捷事务API
The Convenient Transaction API provides the following methods to implement transactions:便捷事务API提供了以下方法来实现事务:
withSession(): Runs the callback passed to it within a session. The API handles the creation and termination of the session automatically.:在会话中运行传递给它的回调。API自动处理会话的创建和终止。withTransaction(): Runs the callback passed to it within a transaction and calls the:在事务中运行传递给它的回调,并在回调返回时调用commitTransaction()method when the callback returns.commitTransaction()方法。
These methods return the value that the callback returns. For example, if a callback you pass to the 这些方法返回回调函数返回的值。例如,如果传递给withTransaction() method returns the document { hello: "world" }, then the withTransaction() method also returns that document.withTransactions()方法的回调返回了文档{ hello: "world" },那么withTransaction()方法也会返回该文档。
Important
To avoid infinite looping errors, ensure that the callback you pass to the 为了避免无限循环错误,请确保传递给withTransaction() method catches any errors that it raises.withTransaction()方法的回调捕获它引发的任何错误。
When you use the Convenient Transaction API, you can propagate return values from the callback as the return values of the 当您使用方便事务API时,您可以将回调的返回值传播为withTransaction() and withSession() methods to work with them elsewhere in your code.withTransaction()和withSession()方法的返回值,以便在代码的其他地方使用它们。
You must perform the following steps when using this API:使用此API时,必须执行以下步骤:
Pass the session instance to each operation that you want to run in that session.将会话实例传递给要在该会话中运行的每个操作。Implement the async为会话中的每个操作实现异步awaitsyntax for each operation in the session.await语法。Avoid parallelism, such as calling the避免并行,例如调用Promise.all()method. Using sessions in parallel usually leads to server errors.Promise.all()方法。并行使用会话通常会导致服务器错误。
The following code demonstrates how to perform a transaction by using the Convenient Transaction API:以下代码演示了如何使用便捷事务API执行事务:
async function convTest(client) {
let txnRes = await client.withSession(async (session) =>
session.withTransaction(async (session) => {
const savingsColl = client.db("bank").collection("savings_accounts");
await savingsColl.findOneAndUpdate(
{account_id: "9876"},
{$inc: {amount: -100 }},
{ session });
const checkingColl = client.db("bank").collection("checking_accounts");
await checkingColl.findOneAndUpdate(
{account_id: "9876"},
{$inc: {amount: 100 }},
{ session });
// ... perform other operations执行其他操作
return "Transaction committed.";
}, null)
);
console.log(txnRes);
}
To see a fully runnable example that uses this API, see the Use the Convenient Transaction API usage example.要查看使用此API的完全可运行的示例,请参阅使用便捷事务API用法示例。
Note
Parallel Operations Not Supported不支持并行操作
The Node.js driver does not support running parallel operations within a single transaction.Node.js驱动程序不支持在单个事务中运行并行操作。
Transaction Options事务选项
You can pass a 您可以将TransactionOptions instance to the startTransaction() and withTransaction() methods to configure how the driver performs a transaction. When you specify an option, it overrides the value of the option that you might have set on your MongoClient instance.TransactionOptions实例传递给startTransaction()和withTransaction()方法,以配置驱动程序如何执行事务。当您指定一个选项时,它会覆盖您可能在MongoClient实例上设置的选项值。
The following table includes options that you can specify in a 下表包括可以在TransactionOptions instance:TransactionOptions实例中指定的选项:
readConcern | |
writeConcern | |
readPreference | |
maxCommitTimeMS |
For a full list of options, see the API documentation for TransactionOptions.有关完整的选项列表,请参阅TransactionOptions的API文档。
Note
The transaction inherits settings from your 除非在事务选项中指定,否则事务将继承MongoClient instance unless you specify them in your transaction options.MongoClient实例的设置。
The following code shows how to define and pass transaction options to the 以下代码显示了如何定义事务选项并将其传递给startTransaction() method:startTransaction()方法:
const txnOpts = {
readPreference: 'primary',
readConcern: { level: 'local' },
writeConcern: { w: 'majority' },
maxCommitTimeMS: 1000
};
session.startTransaction(txnOpts);Transaction Errors事务错误
Because MongoDB transactions are ACID compliant, the driver might produce errors during operation to ensure your data maintains consistent. If the following errors occur, your application must retry the transaction:由于MongoDB事务符合ACID标准,驱动程序在操作过程中可能会产生错误,以确保您的数据保持一致。如果发生以下错误,您的应用程序必须重试事务:
TransientTransactionError: Raised if a write operation encounters an error before the driver commits the transaction. To learn more about this error type, see the TransientTransactionError description on the Drivers API page in the Server manual.:如果写入操作在驱动程序提交事务之前遇到错误,则会引发此问题。要了解有关此错误类型的更多信息,请参阅服务器手册中驱动程序API页面上的TransientTransactionError描述。UnknownTransactionCommitResult: Raised if the commit operation encounters an error. To learn more about this error type, see the UnknownTransactionCommitResult description on the Drivers API page in the Server manual.:如果提交操作遇到错误,则引发。要了解有关此错误类型的更多信息,请参阅服务器手册中驱动程序API页面上的UnknownTransactionCommitResult说明。
The following sections describe how to handle these errors when using different APIs.以下部分描述了使用不同API时如何处理这些错误。
Convenient Transaction API Error Handling方便的事务API错误处理
The Convenient Transaction API incorporates retry logic for these error types. The driver automatically retries the transaction until there is a successful commit.方便事务API包含了这些错误类型的重试逻辑。驱动程序会自动重试事务,直到提交成功。
Core API Error Handling核心API错误处理
If you are using the Core API to perform a transaction, you must add the following error-handling functions to your application:如果使用Core API执行事务,则必须将以下错误处理函数添加到应用程序中:
A function that retries the entire transaction when the driver encounters a当驱动程序遇到TransientTransactionErrorTransientTransactionError时重试整个事务的函数A function that retries the commit operation when the driver encounters an当驱动程序遇到UnknownTransactionCommitResultUnknownTransactionCommitResult时重试提交操作的函数
These functions must run until there is a successful commit or a different error. For an example of this retry logic, see the Core API section on the Drivers API page in the Server manual.这些函数必须运行,直到成功提交或出现其他错误。有关此重试逻辑的示例,请参阅服务器手册中驱动程序API页上的核心API部分。