On this page本页内容
Session.commitTransaction()
New in version 4.0.在版本4.0中新增。
Saves the changes made by the operations in the multi-document transaction and ends the transaction.保存多文档事务中操作所做的更改并结束事务。
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"写关注点进行提交,则可以在故障转移过程中回滚事务。
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。
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.有关更多信息,请参阅事务错误处理。
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.hasOwnProperty("errorLabels") && 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.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(); }