驱动程序 API
Callback API 与 Core API
启动事务,执行指定操作并提交(或在出错时中止)。
自动包含
TransientTransactionError
和UnknownTransactionCommitResult
的错误处理逻辑。
需要显式调用以启动并提交事务。
不包含对
TransientTransactionError
和UnknownTransactionCommitResult
的错误处理逻辑,而是提供对这些错误进行自定义错误处理的灵活性。
回调 API
回调 API 包含以下逻辑:
在事务遇到
TransientTransactionError
错误时将事务作为一个整体进行重试。如果提交操作遇到
UnknownTransactionCommitResult
错误,则重试提交操作。
从 MongoDB 6开始。 0 。 5 ,如果服务器收到TransactionTooLargeForCache
错误,则不会重试事务。
例子
➤ 使用右上角的选择语言下拉菜单来设置本页面上示例的语言。
核心 API
核心事务 API 不包含标记为以下错误的重试逻辑:
TransientTransactionError
。如果事务中的操作返回标记为TransientTransactionError
的错误,则可以将事务作为一个整体进行重试。要处理
TransientTransactionError
,应用程序应显式包含该错误的重试逻辑。UnknownTransactionCommitResult
。如果提交返回标记为UnknownTransactionCommitResult
的错误,则可以重试提交。要处理
UnknownTransactionCommitResult
,应用程序应显式包含该错误的重试逻辑。
例子
➤ 使用右上角的选择语言下拉菜单来设置本页面上示例的语言。
以下示例包含在出现暂时性错误时重试事务的逻辑,以及在出现未知提交错误时重试提交的逻辑:
驱动程序版本
事务错误处理
无论是何种数据库系统,无论是 MongoDB 还是关系型数据库,应用程序都应采取相应措施来处理事务提交期间的错误,并包含事务的重试逻辑。
TransientTransactionError
事务中的 各个 写入操作不可重试,无论retryWrites
的值如何。如果操作遇到 与标签相关 的错误"TransientTransactionError"
,例如当主节点降级时,可以重试整个事务。
回调 API 包含
"TransientTransactionError"
的重试逻辑。核心事务 API 不包含
"TransientTransactionError"
的重试逻辑。要处理"TransientTransactionError"
,应用程序应显式包含错误的重试逻辑。要查看包含瞬时错误重试逻辑的示例,请参阅 Core API 示例。
UnknownTransactionCommitResult
提交操作是可重试写入操作。如果提交操作遇到错误,那么无论 retryWrites
的值如何,MongoDB 驱动程序都会重试提交。
如果提交操作遇到标记为 "UnknownTransactionCommitResult"
的错误,则可以重试提交。
回调 API 包含
"UnknownTransactionCommitResult"
的重试逻辑。核心事务 API 不包含
"UnknownTransactionCommitResult"
的重试逻辑。要处理"UnknownTransactionCommitResult"
,应用程序应显式包含错误的重试逻辑。要查看包含未知提交错误的重试逻辑示例,请参阅 Core API 示例。
TransactionTooLargeForCache
版本 6.0.5 中的新增内容。
从 MongoDB 6.0.5 开始,服务器在收到TransactionTooLargeForCache
错误后不会重试事务。 此错误表示缓存太小,重试可能会失败。
transactionTooLargeForCacheThreshold
阈值的默认值为 0.75
。当事务使用超过 75% 的缓存时,服务器会返回 TransactionTooLargeForCache
而不是重试事务。
在 MongoDB 的早期版本中,服务器会返回 TemporarilyUnavailable
或 WriteConflict
,而不是 TransactionTooLargeForCache
。
使用 setParameter
命令修改错误阈值。
更多信息
mongosh
例子
以下 mongosh
方法适用于事务:
// Create collections: db.getSiblingDB("mydb1").foo.insertOne( {abc: 0}, { writeConcern: { w: "majority", wtimeout: 2000 } } ) db.getSiblingDB("mydb2").bar.insertOne( {xyz: 0}, { writeConcern: { w: "majority", wtimeout: 2000 } } ) // Start a session. session = db.getMongo().startSession( { readPreference: { mode: "primary" } } ); coll1 = session.getDatabase("mydb1").foo; coll2 = session.getDatabase("mydb2").bar; // Start a transaction session.startTransaction( { readConcern: { level: "local" }, writeConcern: { w: "majority" } } ); // Operations inside the transaction try { coll1.insertOne( { abc: 1 } ); coll2.insertOne( { xyz: 999 } ); } catch (error) { // Abort transaction on error session.abortTransaction(); throw error; } // Commit the transaction using write concern set at transaction start session.commitTransaction(); session.endSession();