> For the complete documentation index, see [llms.txt](https://techboys.gitbook.io/performance-best-practices-for-mongodb/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://techboys.gitbook.io/performance-best-practices-for-mongodb/multi-document-acid-transactions.md).

# 多文档ACID事务

> ACID：数据库事务的四个基本要素，即 Atomicity 原子性，Consistency 一致性，Isolation 隔离性，Durablity 持久性。

MongoDB的文档模型支持内嵌文档，而不是传统数据库中的跨表关联。所以单文档的原子性操作能很好的满足大部分应用的事务需求。一次操作中可以更新多个子文档的字段。并且当一个文档被更新后，能够保证完整的隔离性；执行过程中出现任何错误都会立刻回滚此次操作，客户端接收到的是一致性的表现。

MongoDB现有的文档原子性保证将满足一个应用的80-90%事务性需求。他们仍然是保持数据完整性的推荐方法。

MongoDB 4.0 添加了对多文档ACID事务的支持，使开发者更容易地使用MongoDB解决相关问题。同时会让开发者感觉在和关系型数据库的事务很相似，无论是语句，语法，并且可以很容易地添加到应用中。通过快照隔离，MongoDB事务提供了一致的数据视图，强制执行全部或者无任何执行，并且不影响其他工作负载。

对于那些需要嵌套文档事务的操作，这里提供了一些最佳实践：

* 创建长时间运行的事务，或尝试在单个ACID事务中执行过多操作可能会导致WiredTiger缓存的压力很大。 这是因为自创建最旧的快照以来，缓存必须为所有后续写入保持状态。 由于事务在运行时始终使用相同的快照，因此在整个事务期间，新写入会在缓存中累积。 在当前在旧快照上运行的事务提交或中止之前，无法刷新这些写入，此时事务会释放其锁定并且WiredTiger可以驱逐快照。 为了保持可预测的数据库性能级别，开发人员应该考虑以下事项：
* 默认情况下，MongoDB将自动中止任何运行超过60秒的多文档事务。 请注意，如果写入服务器的卷很少，则可以灵活地调整事务的执行时间。 为了解决超时问题，应将事务分解为允许在配置的时间限制内执行的较小部分。 您还应确保使用适当的索引覆盖率正确优化查询模式，以允许在事务中快速访问数据。
* 在事务中可以读取的文档数量没有硬性限制。 作为最佳实践，在事务中不应修改1,000个以上的文档。 对于需要修改1,000多个文档的操作，开发人员应将事务分解为单独处理文档的部分。
* 在MongoDB 4.0中，事务在单个oplog条目中表示，因此必须在16MB文档大小限制内。 虽然更新操作仅存储更新的增量（即，已更改的内容），但插入将存储整个文档。 因此，事务中所有语句的oplog描述组合必须小于16MB。 如果超出此限制，则将中止事务并完全回滚。 因此，事务应该分解为一组较小的操作，可以表示为16MB或更少。
* 当事务中止时，会向驱动程序返回异常并完全回滚事务。 开发人员应添加应用程序逻辑，以捕获并重试因临时异常而中止的事务，例如瞬态网络故障或主副本选举。 通过可重试写入，MongoDB驱动程序将自动重试事务的commit语句。

这里有更丰富的最佳实践 [MongoDB documentation for multi-document transactions](https://docs.mongodb.com/master/core/transactions/)
