Session.abortTransaction()
On this page本页内容
Definition定义
Session.abortTransaction()
-
Terminates the multi-document transaction and rolls back any data changes made by the operations within the transaction. That is, the transaction ends without saving any of the changes made by the operations in 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
abortTransaction
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行为
Atomicity原子性
When a transaction aborts, all data changes made by the writes in the transaction are discarded without ever becoming visible and the transaction ends.当事务中止时,事务中写入的所有数据更改都将被丢弃,而不会变得可见,并且事务结束。
Security安全
If running with auditing, operations in an aborted transaction are still audited.如果使用审核运行,则中止事务中的操作仍将被审核。
Retryable可重试
If the abort operation encounters an error, MongoDB drivers retry the abort operation a single time regardless of whether 如果中止操作遇到错误,无论retryWrites
is set to true
. retryWrites
是否设置为true
,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 and vice versa. hr
数据库中的员工记录进行更改时,您希望确保reporting
数据库中的events
集合与人力资源更改同步,反之亦然。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 employees
collection has a unique index on the employee
field:employees
集合在employee
字段上具有唯一索引:
db.employees.createIndex( { employee: 1 }, { unique: true } )
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, attempts to add a record to the 以下示例打开一个事务,尝试将记录添加到events
collection and add a document to the employees
collection. events
集合,并将文档添加到employees
集合。If the operation encounters an error in either operations or in committing the transaction, the session aborts the transaction.如果操作在操作或提交事务时遇到错误,会话将中止事务。
//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;
}
}
}
}
//Performs inserts and count in a transaction在事务中执行插入和计数
function updateEmployeeInfo(session) {
employeesCollection = session.getDatabase("hr").employees;
eventsCollection = session.getDatabase("reporting").events;
//Start a transaction for the session that uses:启动会话的事务,该会话使用:
// -read concern "snapshot"读取关注“快照”
// -write concern "majority"写下关注“多数”
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );
try{
eventsCollection.insertOne(
{ employee: 3, status: { new: "Active", old: null }, department: { new: "XYZ", old: null } }
);
//Count number of events for employee 3统计员工3的事件数
var countDoc = eventsCollection.aggregate( [ { $match: { employee: 3 } }, { $count: "eventCounts" } ] ).next();
print( "events count (in active transaction): " + countDoc.eventCounts );
//The following operations should fail as an employee ``3`` already exist in employees collection以下操作应失败,因为员工集合中已存在员工“3”
employeesCollection.insertOne(
{ employee: 3, name: { title: "Miss", name: "Terri Bachs" }, status: "Active", department: "XYZ" }
);
} catch (error) {
print("Caught exception during transaction, aborting.");
session.abortTransaction();
throw error;
}
commitWithRetry(session);
} //End of updateEmployeeInfo functionupdateEmployeeInfo函数结束
//Start a session.启动会话。
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
try{
runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
//Do something with error做一些错误的事情
} finally {
session.endSession();
}