Database Manual / Reference / mongosh Methods / Connections / Session

Session.commitTransaction() (mongosh method方法)

Definition定义

Session.commitTransaction()

Saves the changes made by the operations in the multi-document transaction and ends the transaction.保存多文档事务中操作所做的更改并结束事务。

Multi-document transactions are available for both sharded clusters and replica sets.多文档事务可用于分片集群和副本集。

Session.commitTransaction() does not return a value.不返回值。

Important

mongosh Method方法

This page documents a mongosh method. This is not the documentation for database commands or language-specific drivers, such as Node.js.本页记录了一种mongosh方法。这不是数据库命令或特定语言驱动程序(如Node.js)的文档。

For the database command, see the commitTransaction command.有关数据库命令,请参阅commitTransaction命令。

For MongoDB API drivers, refer to the language-specific MongoDB driver documentation.有关MongoDB API驱动程序,请参阅特定语言的MongoDB驱动程序文档

Compatibility兼容性

This method is available in deployments hosted in the following environments:此方法在以下环境中托管的部署中可用:

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud:云中MongoDB部署的完全托管服务

Note

This command is supported in all MongoDB Atlas clusters. 所有MongoDB Atlas集群都支持此命令。For information on Atlas support for all commands, see Unsupported Commands.有关Atlas支持所有命令的信息,请参阅不支持的命令

  • MongoDB Enterprise: The subscription-based, self-managed version of MongoDB:MongoDB的基于订阅的自我管理版本
  • MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB:MongoDB的源代码可用、免费使用和自我管理版本

Behavior行为

Write Concern写关注

When commiting the transaction, the session uses the write concern specified at the transaction start. 提交事务时,会话使用在事务开始时指定的写入关注。See Session.startTransaction().请参阅Session.startTransaction()

If you commit using "w: 1" write concern, your transaction can be rolled back during the failover process.如果使用"w: 1"写关注提交,则可以在故障转移过程中回滚事务

Atomicity原子性

When a transaction commits, all data changes made in the transaction are saved and visible outside the transaction. That is, a transaction will not commit some of its changes while rolling back others.当事务提交时,事务中所做的所有数据更改都会被保存并在事务外部可见。也就是说,一个事务不会在回滚其他更改的同时提交其中的一些更改。

Until a transaction commits, the data changes made in the transaction are not visible outside the transaction.在事务提交之前,事务中所做的数据更改在事务外部不可见。

However, when a transaction writes to multiple shards, not all outside read operations need to wait for the result of the committed transaction to be visible across the shards. 然而,当一个事务写入多个分片时,并非所有外部读取操作都需要等待提交事务的结果在分片之间可见。For example, if a transaction is committed and write 1 is visible on shard A but write 2 is not yet visible on shard B, an outside read at read concern "local" can read the results of write 1 without seeing write 2.例如,如果一个事务已提交,并且写1在分片a上可见,但写2在分片B上尚不可见,则外部读取关注"local"可以读取写1的结果,而看不到写2。

Retryable可重试

If the commit operation encounters an error, MongoDB drivers retry the commit operation a single time regardless of whether retryWrites is set to false. 如果提交操作遇到错误,无论retryWrites是否设置为false,MongoDB驱动程序都会重试一次提交操作。For more information, see Transaction Error Handling.有关更多信息,请参阅事务错误处理

Example示例

Consider a scenario where as changes are made to an employee's record in the hr database, you want to ensure that the events collection in the reporting database are in sync with the hr changes. 考虑一种情况,当对hr数据库中的员工记录进行更改时,您希望确保reporting数据库中的events集合与hr更改同步。That is, you want to ensure that these writes are done as a single transaction, such that either both operations succeed or fail.也就是说,您希望确保这些写入作为单个事务完成,以便两个操作都成功或失败。

The employees collection in the hr database has the following documents:hr数据库中的employees集合包含以下文档:

{ "_id" : ObjectId("5af0776263426f87dd69319a"), "employee" : 3, "name" : { "title" : "Mr.", "name" : "Iba Ochs" }, "status" : "Active", "department" : "ABC" }
{ "_id" : ObjectId("5af0776263426f87dd693198"), "employee" : 1, "name" : { "title" : "Miss", "name" : "Ann Thrope" }, "status" : "Active", "department" : "ABC" }
{ "_id" : ObjectId("5af0776263426f87dd693199"), "employee" : 2, "name" : { "title" : "Mrs.", "name" : "Eppie Delta" }, "status" : "Active", "department" : "XYZ" }

The events collection in the reporting database has the following documents:reporting数据库中的events集合包含以下文档:

{ "_id" : ObjectId("5af07daa051d92f02462644a"), "employee" : 1, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } }
{ "_id" : ObjectId("5af07daa051d92f02462644b"), "employee" : 2, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "XYZ", "old" : null } }
{ "_id" : ObjectId("5af07daa051d92f02462644c"), "employee" : 3, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } }

The following example opens a transaction, updates an employee's status to Inactive in the employees status and inserts a corresponding document to the events collection, and commits the two operations as a single transaction.以下示例打开一个事务,将employees状态更新为Inactive,并将相应的文档插入到events集合中,然后将这两个操作作为单个事务提交。

// Runs the txnFunc and retries if TransientTransactionError encountered

function runTransactionWithRetry(txnFunc, session) {
while (true) {
try {
txnFunc(session); // performs transaction
break;
} catch (error) {
// If transient error, retry the whole transaction
if (error?.errorLabels?.includes("TransientTransactionError") ) {
print("TransientTransactionError, retrying transaction ...");
continue;
} else {
throw error;
}
}
}
}

// Retries commit if UnknownTransactionCommitResult encountered

function commitWithRetry(session) {
while (true) {
try {
session.commitTransaction(); // Uses write concern set at transaction start.
print("Transaction committed.");
break;
} catch (error) {
// Can retry commit
if (error?.errorLabels?.includes("UnknownTransactionCommitResult") ) {
print("UnknownTransactionCommitResult, retrying commit operation ...");
continue;
} else {
print("Error during commit ...");
throw error;
}
}
}
}

// Updates two collections in a transactions

function updateEmployeeInfo(session) {
employeesCollection = session.getDatabase("hr").employees;
eventsCollection = session.getDatabase("reporting").events;

session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );

try{
employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } );
eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
} catch (error) {
print("Caught exception during transaction, aborting.");
session.abortTransaction();
throw error;
}

commitWithRetry(session);
}

// Start a session.
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );

try{
runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
// Do something with error
} finally {
session.endSession();
}