Drivers API驱动程序API
On this page本页内容
Callback API vs Core API
The Callback API:回调API:
Starts a transaction, executes the specified operations, and commits (or aborts on error).启动事务,执行指定的操作,并提交(或在出现错误时中止)。Automatically incorporates error handling logic for自动合并TransientTransactionError
andUnknownTransactionCommitResult
.TransientTransactionError
和UnknownTransactionCommitResult
的错误处理逻辑。
Requires explicit call to start the transaction and commit the transaction.需要显式调用来启动事务并提交事务。Does not incorporate error handling logic for不包含TransientTransactionError
andUnknownTransactionCommitResult
, and instead provides the flexibility to incorporate custom error handling for these errors.TransientTransactionError
和UnknownTransactionCommitResult
的错误处理逻辑,而是提供了为这些错误包含自定义错误处理的灵活性。
Callback API
The callback API incorporates logic:回调API包含以下逻辑:
To retry the transaction as a whole if the transaction encounters a如果事务遇到TransientTransactionError
error.TransientTransactionError
错误,则整体重试事务。To retry the commit operation if the commit encounters an如果提交遇到UnknownTransactionCommitResult
error.UnknownTransactionCommitResult
错误,请重试提交操作。
Starting in MongoDB 6.2, the server does not retry the transaction if it receives a 从MongoDB 6.2开始,如果服务器收到TransactionTooLargeForCache
error.TransactionTooLargeForCache
错误,则不会重试该事务。
Example实例
➤ Use the Select your language drop-down menu in the upper-right to set the language of the examples on this page.
-
Recommended. Use the MongoDB driver updated for the version of your MongoDB deployment.推荐。使用为您的MongoDB部署版本更新的MongoDB驱动程序。For transactions on MongoDB 4.2 deployments (replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2.对于MongoDB 4.2部署上的事务(副本集和分片集群),客户端必须使用为MongoDB 4.2更新的MongoDB驱动程序。 -
When using the drivers, each operation in the transaction must be associated with the session (i.e. pass in the session to each operation).使用驱动程序时,事务中的每个操作都必须与会话相关联(即,将会话传递给每个操作)。 -
Operations in a transaction use transaction-level read concern, transaction-level write concern, and transaction-level read preference.事务中的操作使用事务级读取关注、事务级写入关注和事务级读取首选项。 -
In MongoDB 4.2 and earlier, you cannot create collections in transactions.在MongoDB 4.2及更早版本中,您不能在事务中创建集合。Write operations that result in document inserts (e.g.如果在事务内部运行,则导致文档插入的写入操作(例如,插入或使用insert
or update operations withupsert: true
) must be on existing collections if run inside transactions.upsert:true
的更新操作)必须在现有集合上。 -
Starting in MongoDB 4.4, you can create collections in transactions implicitly or explicitly. See Create Collections and Indexes In a Transaction.从MongoDB 4.4开始,您可以隐式或显式地在事务中创建集合。请参见在事务中创建集合和索引。
The example uses the new callback API for working with transactions, which starts a transaction, executes the specified operations, and commits (or aborts on error). 该示例使用新的回调API处理事务,启动事务、执行指定的操作并提交(或在出现错误时中止)。The new callback API incorporates retry logic for 新回调API包含TransientTransactionError
or UnknownTransactionCommitResult
commit errors.TransientTransactionError
或UnknownTransactionCommitResult
提交错误的重试逻辑。
//For a replica set, include the replica set name and a seedlist of the members in the URI string;对于副本集,在URI字符串中包括副本集名称和成员的种子列表;e.g.
// const uri = 'mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl'
//For a sharded cluster, connect to the mongos instances;对于分片集群,连接到mongos实例;e.g.
// const uri = 'mongodb://mongos0.example.com:27017,mongos1.example.com:27017/'
const client = new MongoClient(uri);
await client.connect();
//Prereq: Create collections.准备工作:创建集合。
await client
.db('mydb1')
.collection('foo')
.insertOne({ abc: 0 }, { writeConcern: { w: 'majority' } });
await client
.db('mydb2')
.collection('bar')
.insertOne({ xyz: 0 }, { writeConcern: { w: 'majority' } });
//Step 1: Start a Client Session步骤1:启动客户端会话
const session = client.startSession();
//Step 2: Optional. Define options to use for the transaction步骤2:可选。定义用于事务的选项
const transactionOptions = {
readPreference: 'primary',
readConcern: { level: 'local' },
writeConcern: { w: 'majority' }
};
//Step 3: Use withTransaction to start a transaction, execute the callback, and commit (or abort on error)步骤3:使用withTransaction启动事务、执行回调并提交(或在出现错误时中止)
//Note: The callback for withTransaction MUST be async and/or return a Promise.注意:withTransaction的回调必须是异步的和/或返回Promise。
try {
await session.withTransaction(async () => {
const coll1 = client.db('mydb1').collection('foo');
const coll2 = client.db('mydb2').collection('bar');
//Important:: You must pass the session to the operations重要提示:您必须将会话传递给操作
await coll1.insertOne({ abc: 1 }, { session });
await coll2.insertOne({ xyz: 999 }, { session });
}, transactionOptions);
} finally {
await session.endSession();
await client.close();
}Core API
The core transaction API does not incorporate retry logic for errors labeled:核心事务API不包含标记为以下错误的重试逻辑:
TransientTransactionError
. If an operation in a transaction returns an error labeled。如果事务中的操作返回标记为TransientTransactionError
, the transaction as a whole can be retried.TransientTransactionError
的错误,则可以重试整个事务。
To handle为了处理TransientTransactionError
, applications should explicitly incorporate retry logic for the error.TransientTransactionError
,应用程序应该显式地包含错误的重试逻辑。UnknownTransactionCommitResult
. If the commit returns an error labeled。如果提交返回标记为UnknownTransactionCommitResult
, the commit can be retried.UnknownTransactionCommitResult
的错误,则可以重试提交。
To handle若要处理UnknownTransactionCommitResult
, applications should explicitly incorporate retry logic for the error.UnknownTransactionCommitResult
,应用程序应明确包含错误的重试逻辑。
Example实例
➤ Use the Select your language drop-down menu in the upper-right to set the language of the examples on this page.
The following example incorporates logic to retry the transaction for transient errors and retry the commit for unknown commit error:以下示例包含了针对暂时错误重试事务和针对未知提交错误重试提交的逻辑:Important
To associate read and write operations with a transaction, you must pass the session to each operation in the transaction.要将读写操作与事务相关联,必须将会话传递给事务中的每个操作。async function commitWithRetry(session) {
try {
await session.commitTransaction();
console.log('Transaction committed.');
} catch (error) {
if (error.hasErrorLabel('UnknownTransactionCommitResult')) {
console.log('UnknownTransactionCommitResult, retrying commit operation ...');
await commitWithRetry(session);
} else {
console.log('Error during commit ...');
throw error;
}
}
}
async function runTransactionWithRetry(txnFunc, client, session) {
try {
await txnFunc(client, session);
} catch (error) {
console.log('Transaction aborted. Caught exception during transaction.');
//If transient error, retry the whole transaction如果出现暂时错误,请重试整个事务
if (error.hasErrorLabel('TransientTransactionError')) {
console.log('TransientTransactionError, retrying transaction ...');
await runTransactionWithRetry(txnFunc, client, session);
} else {
throw error;
}
}
}
async function updateEmployeeInfo(client, session) {
session.startTransaction({
readConcern: { level: 'snapshot' },
writeConcern: { w: 'majority' },
readPreference: 'primary'
});
const employeesCollection = client.db('hr').collection('employees');
const eventsCollection = client.db('reporting').collection('events');
await employeesCollection.updateOne(
{ employee: 3 },
{ $set: { status: 'Inactive' } },
{ session }
);
await eventsCollection.insertOne(
{
employee: 3,
status: { new: 'Inactive', old: 'Active' }
},
{ session }
);
try {
await commitWithRetry(session);
} catch (error) {
await session.abortTransaction();
throw error;
}
}
return client.withSession(session =>
runTransactionWithRetry(updateEmployeeInfo, client, session)
);
Driver Versions驱动程序版本
For transactions on MongoDB 4.2 deployments (replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2:对于MongoDB 4.2部署上的事务(副本集和分片集群),客户端必须使用为MongoDB 4.2更新的MongoDB驱动程序:
Transaction Error Handling事务错误处理
Regardless of the database system, whether MongoDB or relational databases, applications should take measures to handle errors during transaction commits and incorporate retry logic for transactions.无论数据库系统是MongoDB还是关系数据库,应用程序都应该采取措施来处理事务提交过程中的错误,并为事务引入重试逻辑。
TransientTransactionError
The individual write operations inside the transaction are not retryable, regardless of the value of无论retryWrites
.retryWrites
的值如何,事务中的各个写入操作都是不可重试的。If an operation encounters an error associated with the label如果操作遇到与标签![]()
"TransientTransactionError"
, such as when the primary steps down, the transaction as a whole can be retried."TransientTransactionError"
相关联的错误,例如当主操作停止时,则可以重试整个事务。
The callback API incorporates retry logic for回调API包含"TransientTransactionError"
."TransientTransactionError"
的重试逻辑。The core transaction API does not incorporate retry logic for核心事务API未包含"TransientTransactionError"
."TransientTransactionError"
的重试逻辑。To handle为了处理"TransientTransactionError"
, applications should explicitly incorporate retry logic for the error."TransientTransactionError"
,应用程序应该明确地包含错误的重试逻辑。
UnknownTransactionCommitResult
The commit operations are retryable write operations.提交操作是可重试的写入操作。If the commit operation encounters an error, MongoDB drivers retry the commit regardless of the value of如果提交操作遇到错误,MongoDB驱动程序将重试提交,而不考虑retryWrites
.retryWrites
的值。
If the commit operation encounters an error labeled如果提交操作遇到标记为"UnknownTransactionCommitResult"
, the commit can be retried."UnknownTransactionCommitResult"
的错误,则可以重试提交。
The callback API incorporates retry logic for回调API包含"UnknownTransactionCommitResult"
."UnknownTransactionCommitResult"
的重试逻辑。- The core transaction API does not incorporate retry logic for
"UnknownTransactionCommitResult"
. To handle"UnknownTransactionCommitResult"
, applications should explicitly incorporate retry logic for the error.
TransactionTooLargeForCache
New in version 6.2.6.2版新增。
Starting in MongoDB 6.2, the server does not retry the transaction if it receives a从MongoDB 6.2开始,如果服务器收到TransactionTooLargeForCache
error.TransactionTooLargeForCache
错误,则不会重试该事务。This error means the cache is too small and a retry is likely to fail.此错误意味着缓存太小,重试可能会失败。
The default value for thetransactionTooLargeForCacheThreshold
threshold is0.75
.transactionTooLargeForCacheThreshold
阈值的默认值为0.75
。The server returns当事务使用超过75%的缓存时,服务器返回TransactionTooLargeForCache
instead of retrying the transaction when the transaction uses more than 75% of the cache.TransactionTooLargeForCache
,而不是重试该事务。
In earlier versions of MongoDB, the server returns在早期版本的MongoDB中,服务器返回TemporarilyUnavailable
orWriteConflict
instead ofTransactionTooLargeForCache
.TemporarilyUnavailable
或WriteConflict
,而不是TransactionTooLargeForCache
。
Use the使用setParameter
command to modify the error threshold.setParameter
命令可以修改错误阈值。
Driver Version Errors驱动程序版本错误
On sharded clusters with multiple在具有多个mongos
instances, performing transactions with drivers updated for MongoDB 4.0 (instead of MongoDB 4.2) will fail and can result in errors, including:mongos
实例的分片集群上,使用为MongoDB 4.0(而不是MongoDB 4.2)更新的驱动程序执行事务将失败,并可能导致错误,包括:Note
Your driver may return a different error.您的驱动程序可能会返回不同的错误。Refer to your driver's documentation for details.有关详细信息,请参阅您的驾驶员文档。
Error Code错误代码Error Message错误消息251 cannot continue txnId -1 for session ... with txnId 1
50940 cannot commit with no participants
For transactions on MongoDB 4.2 deployments (replica sets and sharded clusters), use the MongoDB drivers updated for MongoDB 4.2对于MongoDB 4.2部署上的事务(副本集和分片集群),请使用为MongoDB 4.2更新的MongoDB驱动程序
Additional Information附加信息
mongosh
Example实例
The following以下mongosh
methods are available for transactions:mongosh
方法可用于事务:Note
The为了简单起见,mongosh
example omits retry logic and robust error handling for simplicity's sake.mongosh
示例省略了重试逻辑和健壮的错误处理。For a more practical example of incorporating transactions in applications, see Transaction Error Handling instead.有关在应用程序中合并事务的更实用的示例,请参阅事务错误处理。//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();