Session.commitTransaction()
On this page本页内容
Definition定义
Session.commitTransaction()
-
Saves the changes made by the operations in the multi-document transaction and ends the transaction.保存多文档事务中的操作所做的更改并结束事务。Importantmongosh Method
This page documents a
mongosh
method. This is not the documentation for database commands or language-specific drivers, such as Node.js.For the database command, see the
commitTransaction
command.For MongoDB API drivers, refer to the language-specific MongoDB driver documentation.
For the legacy
mongo
shell documentation, refer to the documentation for the corresponding MongoDB Server release:Changed in version 4.2.4.2版更改。Starting in MongoDB 4.2, multi-document transactions are available for both sharded clusters and replica sets.从MongoDB 4.2开始,多文档事务可用于分片集群和副本集。
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 例如,如果事务已提交,并且写1在分片A上可见,但写2在分片B上还不可见,则外部读取时关注"local"
can read the results of write 1 without seeing write 2."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.Inactive
,并将相应的文档插入到events
集合中,然后将这两个操作作为单个事务提交。
//Runs the txnFunc and retries if TransientTransactionError encountered如果遇到TransientTransactionError,则运行txnFunc并重试
function runTransactionWithRetry(txnFunc, session) {
while (true) {
try {
txnFunc(session); //performs transaction执行事务
break;
} catch (error) {
//If transient error, retry the whole transaction如果出现暂时错误,请重试整个事务
if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes("TransientTransactionError") ) {
print("TransientTransactionError, retrying transaction ...");
continue;
} else {
throw error;
}
}
}
}
//Retries commit if UnknownTransactionCommitResult encountered如果遇到UnknownTransactionCommitResult,则重试提交
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.hasOwnProperty("errorLabels") && 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();
}