The following page lists some production considerations for running transactions. These apply whether you run transactions on replica sets or sharded clusters. 下一页列出了运行事务的一些生产注意事项。无论您是在副本集还是分片集群上运行事务,这些都适用。For running transactions on sharded clusters, see also the Production Considerations (Sharded Clusters) for additional considerations that are specific to sharded clusters.对于在分片集群上运行事务,另请参阅生产考虑因素(分片集群),了解分片集群特有的其他考虑因素。
Availability可用性
MongoDB standalone deployments do not support transactions. To use transactions, your deployment must be a multiple node replica set.MongoDB单机版部署不支持事务。要使用事务,部署必须是多节点副本集。MongoDB supports multi-document transactions on replica sets.MongoDB支持副本集上的多文档事务。Distributed transactions add support for multi-document transactions on sharded clusters and incorporates the existing support for multi-document transactions on replica sets.分布式事务增加了对分片集群上多文档事务的支持,并整合了对副本集上多文档事务的现有支持。
Note
Distributed Transactions and Multi-Document Transactions分布式事务和多文档事务
The two terms are synonymous. Distributed transactions refer to multi-document transactions on sharded clusters and replica sets. Multi-document transactions (whether on sharded clusters or replica sets) are also known as distributed transactions.这两个词是同义词。分布式事务是指分片集群和副本集上的多文档事务。多文档事务(无论是在分片集群还是副本集上)也称为分布式事务。
Feature Compatibility功能兼容性
To use transactions, the featureCompatibilityVersion for all members of the deployment must be at least:要使用事务,部署所有成员的featureCompatibilityVersion必须至少为:
featureCompatibilityVersion | |
|---|---|
| Replica Set | 4.0 |
| Sharded Cluster | 4.2 |
To check the FCV for a member, connect to the member and run the following command:要检查成员的FCV,请连接到该成员并运行以下命令:
db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
For more information, see the 有关更多信息,请参阅setFeatureCompatibilityVersion reference page.setFeatureCompatibilityVersion参考页面。
Runtime Limit运行时间限制
Note
To configure maximum transaction lifetimes in MongoDB Atlas, see Set Transaction Lifetime in the Atlas documentation.要在MongoDB Atlas中配置最大事务生存期,请参阅Atlas文档中的设置事务生存期。
By default, a transaction must have a runtime of less than one minute. You can modify this limit using 默认情况下,事务的运行时间必须小于一分钟。您可以使用transactionLifetimeLimitSeconds for the mongod instances. mongod实例的transactionLifetimeLimitSeconds修改此限制。For sharded clusters, the parameter must be modified for all shard replica set members. Transactions that exceeds this limit are considered expired and will be aborted by a periodic cleanup process.对于分片集群,必须修改所有分片副本集成员的参数。超过此限制的事务将被视为已过期,并将通过定期清理过程中止。
For sharded clusters, you can also specify a 对于分片集群,您还可以在maxTimeMS limit on commitTransaction. For more information, see Sharded Clusters Transactions Time Limit.commitTransaction上指定maxTimeMS限制。有关更多信息,请参阅分片群集事务时间限制。
Oplog Size Limit操作日志大小限制
MongoDB creates as many oplog entries as necessary to the encapsulate all write operations in a transaction, instead of a single entry for all write operations in the transaction. This removes the 16MB total size limit for a transaction imposed by the single oplog entry for all its write operations. MongoDB根据需要创建尽可能多的oplog条目,以将所有写入操作封装在事务中,而不是为事务中的所有写入操作创建一个条目。这消除了单个oplog条目对其所有写入操作施加的事务总大小限制16MB。Although the total size limit is removed, each oplog entry still must be within the BSON document size limit of 16MB.虽然删除了总大小限制,但每个oplog条目仍必须在16MB的BSON文档大小限制内。
WiredTiger CacheWiredTiger缓存
To prevent storage cache pressure from negatively impacting the performance:为防止存储缓存压力对性能产生负面影响:
When you abandon a transaction, abort the transaction.当您放弃事务时,请中止事务。When you encounter an error during individual operation in the transaction, abort and retry the transaction.当您在事务的单个操作中遇到错误时,请中止并重试事务。
The transactionLifetimeLimitSeconds also ensures that expired transactions are aborted periodically to relieve storage cache pressure.transactionLifetimeLimitSeconds还可确保定期中止过期的事务,以缓解存储缓存压力。
Note
If you have an uncommitted transaction that causes excessive pressure on the WiredTiger cache, the transaction aborts and returns a write conflict error.如果您有一个未提交的事务,导致WiredTiger缓存压力过大,则该事务将中止并返回写冲突错误。
If a transaction is too large to ever fit in the WiredTiger cache, the transaction aborts and returns a 如果事务太大,无法放入WiredTiger缓存,则事务将中止并返回TransactionTooLargeForCache error.TransactionTooLargeForCache错误。
Transactions and Security事务和安全
If running with access control, you must have privileges for the operations in the transaction.如果使用访问控制运行,则必须具有事务中操作的权限。If running with auditing, operations in an aborted transaction are still audited. However, there is no audit event that indicates that the transaction aborted.如果使用审核运行,则中止事务中的操作仍将被审核。但是,没有审计事件表明事务已中止。
Shard Configuration Restriction分片配置限制
You cannot run transactions on a sharded cluster that has a shard with 您无法在具有writeConcernMajorityJournalDefault set to false (such as a shard with a voting member that uses the in-memory storage engine).writeConcernMajorityJournalDefault设置为false的分片的分片集群上运行事务(例如具有使用内存存储引擎的投票成员的分片)。
Sharded Clusters and Arbiters分片集群和仲裁者
You cannot change a shard key using a transaction if the replica set has an arbiter. Arbiters cannot participate in the data operations required for multi-shard transactions.如果副本集有仲裁器,则无法使用事务更改分片键。仲裁员不能参与多分片事务所需的数据操作。
Transactions whose write operations span multiple shards will error and abort if any transaction operation reads from or writes to a shard that contains an arbiter.如果任何事务操作从包含仲裁器的分片读取或写入,则写操作跨越多个分片的事务将出错并中止。
Acquiring Locks获取锁
By default, transactions wait up to 默认情况下,事务等待最多5 milliseconds to acquire locks required by the operations in the transaction. If the transaction cannot acquire its required locks within the 5 milliseconds, the transaction aborts.5毫秒以获取事务中操作所需的锁。如果事务无法在5毫秒内获取所需的锁,则事务中止。
Transactions release all locks upon abort or commit.事务在中止或提交时释放所有锁。
Tip
When creating or dropping a collection immediately before starting a transaction, if the collection is accessed within the transaction, issue the create or drop operation with write concern 在启动事务之前立即创建或删除集合时,如果在事务中访问了该集合,则发出带有写关注"majority" to ensure that the transaction can acquire the required locks."majority"的创建或删除操作,以确保事务能够获取所需的锁。
Lock Request Timeout锁定请求超时
Note
MongoDB Atlas clusters restrict the use of the MongoDB Atlas集群限制了setParameter command. setParameter命令的使用。For more information, see Unsupported Commands in Atlas in the Atlas documentation.有关更多信息,请参阅Atlas文档中的Atlas中不支持的命令。
To modify your Atlas cluster parameters, contact Atlas Support.要修改Atlas集群参数,请联系Atlas支持。
You can use the 您可以使用maxTransactionLockRequestTimeoutMillis parameter to adjust how long transactions wait to acquire locks. maxTransactionLockRequestTimeoutMillis参数来调整事务等待获取锁的时间。Increasing 增加maxTransactionLockRequestTimeoutMillis allows operations in the transactions to wait the specified time to acquire the required locks. maxTransactionLockRequestTimeoutMillis允许事务中的操作等待指定时间以获取所需的锁。This can help obviate transaction aborts on momentary concurrent lock acquisitions, like fast-running metadata operations. However, this could possibly delay the abort of deadlocked transaction operations.这可以帮助避免瞬时并发锁获取时的事务中止,如快速运行的元数据操作。然而,这可能会延迟死锁事务操作的中止。
You can also use operation-specific timeout by setting 您还可以通过将maxTransactionLockRequestTimeoutMillis to -1.maxTransactionLockRequestTimeoutMillis设置为-1来使用特定于操作的超时。
Pending DDL Operations and Transactions待处理的DDL操作和事务
If a multi-document transaction is in progress, new DDL operations that affect the same database(s) or collection(s) wait behind the transaction. While these pending DDL operations exist, new transactions that access the same database(s) or collection(s) as the pending DDL operations cannot obtain the required locks and and will abort after waiting 如果正在进行多文档事务,则影响同一数据库或集合的新DDL操作将在事务之后等待。虽然存在这些挂起的DDL操作,但访问与挂起的DDL操作相同的数据库或集合的新事务无法获得所需的锁,并将在等待maxTransactionLockRequestTimeoutMillis. maxTransactionLockRequestTimeoutMillis后中止。In addition, new non-transaction operations that access the same database(s) or collection(s) will block until they reach their 此外,访问同一数据库或集合的新非事务操作将被阻止,直到它们达到maxTimeMS limit.maxTimeMS限制。
Consider the following scenarios:考虑以下情况:
DDL Operation That Requires a Collection Lock需要集合锁的DDL操作While an in-progress transaction is performing various CRUD operations on the当正在进行的事务对employeescollection in thehrdatabase, an administrator issues thedb.collection.createIndex()DDL operation against theemployeescollection.createIndex()requires an exclusive collection lock on the collection.hr(人力资源)数据库中的employees集合执行各种CRUD操作时,管理员会对employees集合发出db.collection.createIndex()DDL操作。createIndex()要求对集合设置独占集合锁。Until the in-progress transaction completes, the在进行中的事务完成之前,createIndex()operation must wait to obtain the lock.createIndex()操作必须等待以获取锁。Any new transaction that affects the任何影响employeescollection and starts while thecreateIndex()is pending must wait until aftercreateIndex()completes.employees集合并在createIndex()挂起时启动的新事务都必须等到createIndex()。The pending挂起的createIndex()DDL operation does not affect transactions on other collections in thehrdatabase.createIndex()DDL操作不会影响hr数据库中其他集合上的事务。For example, a new transaction on the例如,contractorscollection in thehrdatabase can start and complete as normal.hr数据库中contractors(承包商)集合的新事务可以正常启动和完成。DDL Operation That Requires a Database Lock需要数据库锁的DDL操作While an in-progress transaction is performing various CRUD operations on the当一个正在进行的事务正在对employeescollection in thehrdatabase, an administrator issues therenameCollectionDDL operation to rename thevendors.contractorscollection tohr.contractors.hr数据库中的employees集合执行各种CRUD操作时,管理员会发出renameCollectionDDL操作,将供应商承包商集合重命名为人力资源承包商。当目标数据库(renameCollectionrequires a database lock on the target database (hr) when it differs from the source database (vendors).hr)与源数据库(vendors(供应商))不同时,renameCollection要求对其进行数据库锁定。Until the in-progress transaction completes, the在进行中的事务完成之前,renameCollectionoperation must wait to obtain the lock.renameCollection操作必须等待以获取锁。Any new transaction that affects the任何影响hrdatabase or any of its collections and starts while therenameCollectionis pending must wait until afterrenameCollectioncompletes.hr数据库或其任何集合并在renameCollection挂起时启动的新事务都必须等到renameCollection完成。
In either scenario, if the DDL operation remains pending for more than 在任何一种情况下,如果DDL操作保持挂起状态的时间超过maxTransactionLockRequestTimeoutMillis, pending transactions waiting behind that operation abort. maxTransactionLockRequestTimeoutMillis,则等待该操作的挂起事务将中止。That is, the value of 也就是说,maxTransactionLockRequestTimeoutMillis must at least cover the time required for the in-progress transaction and the pending DDL operation to complete.maxTransactionLockRequestTimeoutMillis的值必须至少涵盖正在进行的事务和挂起的DDL操作完成所需的时间。
In-progress Transactions and Write Conflicts进行中事务和写入冲突
If a transaction is in progress and a write outside the transaction modifies a document that an operation in the transaction later tries to modify, the transaction aborts because of a write conflict.如果事务正在进行中,并且事务外部的写入修改了事务中的操作稍后试图修改的文档,则事务会因写入冲突而中止。
If a transaction is in progress and has taken a lock to modify a document, when a write outside the transaction tries to modify the same document, the write waits until the transaction ends.如果事务正在进行中并且已锁定以修改文档,则当事务外部的写入尝试修改同一文档时,写入将等待事务结束。
In-progress Transactions and Stale Reads正在进行的事务和过时的读取
Read operations inside a transaction can return old data, which is known as a stale read. 事务内的读取操作可能会返回旧数据,这被称为过时读取。Read operations inside a transaction are not guaranteed to see writes performed by other committed transactions or non-transactional writes. For example, consider the following sequence:事务内的读取操作不能保证看到其他已提交事务或非事务性写入执行的写入。例如,考虑以下顺序:
A transaction is in-progress.事务正在进行中。A write outside the transaction deletes a document.事务外的写入操作会删除文档。A read operation inside the transaction can read the now-deleted document since the operation uses a snapshot from before the write operation.事务中的读取操作可以读取现在已删除的文档,因为该操作使用了写入操作之前的快照。
To avoid stale reads inside transactions for a single document, you can use the 为了避免对单个文档的事务内部进行过时的读取,您可以使用db.collection.findOneAndUpdate() method. db.collection.findOneAndUpdate()方法。The following 下面的mongosh example demonstrates how you can use db.collection.findOneAndUpdate() to take a write lock and ensure that your reads are up to date:mongosh示例演示了如何使用db.collection.findOneAndUpdate()获取写锁并确保读取是最新的:
Insert a document into the employees collection将文档插入employees集合
employees collectiondb.getSiblingDB("hr").employees.insertOne(
{ _id: 1, status: "Active" }
)Start a session启动会话
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } )Start a transaction启动事务
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } )
employeesCollection = session.getDatabase("hr").employeesUse db.collection.findOneAndUpdate() inside the transaction在事务中使用db.collection.findOneAndUpdate()
db.collection.findOneAndUpdate() inside the transactionemployeeDoc = employeesCollection.findOneAndUpdate(
{ _id: 1, status: "Active" },
{ $set: { lockId: ObjectId() } },
{ returnNewDocument: true }
)
Note that inside the transaction, the 请注意,在事务内部,findOneAndUpdate operation sets a new lockId field. You can set lockId field to any value, as long as it modifies the document. By updating the document, the transaction acquires a lock.findOneAndUpdate操作设置了一个新的lockId字段。您可以将lockId字段设置为任何值,只要它修改文档即可。通过更新文档,事务获得了锁。
If an operation outside of the transaction attempts to modify the document before you commit the transaction, MongoDB returns a write conflict error to the external operation.如果事务外部的操作试图在提交事务之前修改文档,MongoDB会向外部操作返回写冲突错误。
Commit the transaction提交事务
session.commitTransaction()
After you commit the transaction, MongoDB releases the lock.提交事务后,MongoDB会释放锁。
Note
If any operation in the transaction fails, the transaction aborts and all data changes made in the transaction are discarded without ever becoming visible in the collection.如果事务中的任何操作失败,事务将中止,事务中所做的所有数据更改都将被丢弃,而不会在集合中可见。
In-progress Transactions and Chunk Migration进行中事务和块迁移
Chunk migration acquires exclusive collection locks during certain stages.块迁移在某些阶段获得独占集合锁。
If an ongoing transaction has a lock on a collection and a chunk migration that involves that collection starts, these migration stages must wait for the transaction to release the locks on the collection, thereby impacting the performance of chunk migrations.如果正在进行的事务对集合有锁,并且涉及该集合的块迁移开始,则这些迁移阶段必须等待事务释放对集合的锁,从而影响块迁移的性能。
If a chunk migration interleaves with a transaction (for instance, if a transaction starts while a chunk migration is already in progress and the migration completes before the transaction takes a lock on the collection), the transaction errors during the commit and aborts.如果块迁移与事务交织在一起(例如,如果事务在块迁移已经进行的情况下开始,并且迁移在事务锁定集合之前完成),则事务在提交过程中会出错并中止。
Depending on how the two operations interleave, some sample errors include (the error messages have been abbreviated):根据这两个操作的交织方式,一些示例错误包括(错误消息已缩写):
an error from cluster data placement change ... migration commit in progress for <namespace>Cannot find shardId the chunk belonged to at cluster time ...
Outside Reads During Commit提交过程中的外部阅读
During the commit for a transaction, outside read operations may try to read the same documents that will be modified by the transaction. If the transaction writes to multiple shards, then during the commit attempt across the shards:在事务提交期间,外部读取操作可能会尝试读取将被事务修改的相同文档。如果事务写入多个分片,那么在跨分片的提交尝试期间:
Outside reads that use read concern使用读取关注"snapshot"or"linearizable"wait until all writes of a transaction are visible."snapshot"或"linearizable"的外部读取会等到事务的所有写入都可见。Outside reads that are part of causally consistent sessions (those that include afterClusterTime) wait until all writes of a transaction are visible.作为因果一致会话一部分的外部读取(包括afterClusterTime)会等待事务的所有写入可见。Outside reads using other read concerns do not wait until all writes of a transaction are visible, but instead read the before-transaction version of the documents.使用其他读取关注的外部读取不会等到事务的所有写入都可见,而是读取文档的事务前版本。