Session.abortTransaction()
定义
Session.abortTransaction()
终止多文档事务,并回滚ACID 事务中操作所做的任何数据更改。 也就是说,ACID 事务结束时不保存ACID 事务中操作所做的任何更改。
多文档事务适用于分片集群和副本集。
Session.abortTransaction()
不返回值。重要
mongosh 方法
本页面提供
mongosh
方法的相关信息。这不是数据库命令或特定语言驱动程序(例如 Node.js)的相关文档。有关数据库命令,请参阅
abortTransaction
命令。如需了解 MongoDB API 驱动程序,请参阅特定语言的 MongoDB 驱动程序文档。
兼容性
此方法可用于以下环境中托管的部署:
MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务
注意
所有 MongoDB Atlas 集群都支持此命令。有关 Atlas 对所有命令的支持的信息,请参阅不支持的命令。
MongoDB Enterprise:基于订阅、自我管理的 MongoDB 版本
MongoDB Community:源代码可用、免费使用且可自行管理的 MongoDB 版本
行为
原子性(Atomicity)
当事务中止时,事务中通过写入进行的所有数据更改都会丢弃且变得不可见,同时事务结束。
安全性
如果以审核方式运行,中止的事务中的操作仍会被审核。
可重试
如果中止操作遇到错误,无论是否将 retryWrites
设置为 true
,MongoDB 驱动程序都会重试一次中止操作。有关详细信息,请参阅事务错误处理。
例子
考虑这样一种情况:当对 hr
数据库中的员工记录进行更改时,您希望确保 reporting
数据库中的 events
集合与 hr
更改同步。换言之,您希望确保这些写入作为单个事务完成,以便两个操作要么成功,要么失败。
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" }
employees
集合具有针对 employee
字段的唯一复合索引:
db.employees.createIndex( { employee: 1 }, { unique: true } )
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 } }
以下示例打开一个事务,尝试将记录添加到 events
集合并将文档添加到 employees
集合。如果操作在操作或提交事务时遇到错误,会话将中止事务。
// 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; } } } } // 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 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 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 function // Start a session. session = db.getMongo().startSession( { readPreference: { mode: "primary" } } ); try{ runTransactionWithRetry(updateEmployeeInfo, session); } catch (error) { // Do something with error } finally { session.endSession(); }