事务简介

事务是数据库中处理的逻辑单元,包括一个或多个数据库操作,既可以是读操作,也可以是写操作。在某些情况下,作为这个逻辑处理单元的一部分,应用程序可能需要对多个文档(在一个或多个集合中)进行读写。事务的一个重要方面是它永远不会只完成一部分——它要么成功,要么失败。

要使用事务,你所部署的 MongoDB 必须是 MongoDB 4.2 或更高版本,MongoDB 的驱动程序必须更新为 MongoDB 4.2 或更高版本。MongoDB 提供了一个驱动程序兼容性参考页面,可以用来确保 MongoDB 驱动程序版本的兼容性。

ACID的定义

ACID 是一个“真正”事务所需要具备的一组属性集合。ACID 是原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)的缩写。ACID 事务可以保证数据和数据库状态的有效性,即使在出现断电或其他错误的情况下也是如此。

原子性确保了事务中的所有操作要么都被应用,要么都不被应用。事务永远不能应用部分操作,要么被提交,要么被中止。

一致性确保了如果事务成功,那么数据库将从一个一致性状态转移到下一个一致性状态。

隔离性是允许多个事务同时在数据库中运行的属性。它保证了一个事务不会查看到任何其他事务的部分结果,这意味着多个事务并行运行与依次运行每个事务所获得的结果相同。

持久性确保了在提交事务时,即使系统发生故障,所有数据也都会保持持久化。

当数据库满足所有这些属性并且只有成功的事务才会被处理时,它就被称为是符合ACID 的数据库。如果在事务完成之前发生故障,那么 ACID 确保不会更改任何数据。

使用事务的注意事项

MongoDB 提供了两种 API 来使用事务。第一种是与关系数据库类似的语法(如start_transaction 和 commit_transaction),称为核心 API;第二种称为回调API,这是使用事务的推荐方法。
在这里插入图片描述
核心 API 不为大多数错误提供重试逻辑,它要求开发人员为操作、事务提交函数以及所需的任何重试和错误逻辑手动编写代码。

与核心 API 不同,回调 API 提供了一个单独的函数,该函数封装了大量功能,包括启动与指定逻辑会话关联的事务、执行作为回调函数提供的函数以及提交事务(或在出现错误时中止)。此函数还包含了处理提交错误的重试逻辑。在MongoDB 4.2 中添加回调 API 是为了简化使用事务的应用程序开发,也便于添加处理事务错误的应用程序重试逻辑。

在这两种 API 中,都是由开发人员负责启动事务使用的逻辑会话。这两种 API 都要求事务中的操作与特定的逻辑会话相关联(例如,将会话传递给每个操作)。MongoDB 中的逻辑会话会在整个 MongoDB 部署的上下文中跟踪操作的时间和顺序。逻辑会话或服务器端会话是底层框架的一部分,其被客户端会话用于支持MongoDB 中的可重试写入和因果一致性——这两个特性都是作为支持事务所需基础的一部分在 MongoDB 3.6 中添加的。在 MongoDB 中,一个特定的读写操作序列被定义为因果一致的客户端会话,它们的顺序反映了因果关系。客户端会话由应用程序启动,并用于与服务器端会话进行交互。

在 MongoDB 的多文档事务中,只能对已存在的集合或数据库执行读写(CRUD)操作。如示例所示,如果希望将操作加入事务中,则必须首先在事务之外创建集合。在事务中不允许创建、删除集合或者进行索引操作。

对应用程序的事务限制进行调优

时间和oplog大小限制

在 MongoDB 事务中有两类主要的限制。第一类与事务的时间限制有关,控制特定事务可以运行多长时间、事务等待获取锁的时间以及所有事务将运行的最大长度。第二类与 MongoDB 的 oplog 条目和单个条目的大小限制有关。

一、时间限制
事务的默认最大运行时间是 1 分钟。可以通过在 mongod 实例级别上修改transactionLifetimeLimitSeconds 的限制来增加。对于分片集群,必须在所有分片副本集成员上设置该参数。超过此时间后,事务将被视为已过期,并由定期运行的清理进程中止。清理进程每 60 秒或每 transactionLifetimeLimitSeconds/2 运行一次,以较小的值为准。

要显式设置事务的时间限制,建议在提交事务时指定 maxTimeMS 参数。如果 maxTimeMS 没有设置,那么将使用 transactionLifetimeLimitSeconds;如果设置了 maxTimeMS,但这个值超过了 transactionLifetimeLimitSeconds,那么还是会使用 transactionLifetimeLimitSeconds。

事务等待获取其操作所需锁的默认最大时间是 5 毫秒。可以通过修改由maxTransactionLockRequestTimeoutMillis 参数控制的限制来增加。如果事务在此期间无法获得锁,则该事务会被中止。maxTransactionLockRequestTimeoutMillis 可以设置为 0、-1 或大于 0 的数字。将其设置为 0 意味着,如果事务无法立即获得所需的所有锁,则该事务会被中止。设置为 -1 将使用由 maxTimeMS 参数所指定的特定于操作的超时时间。任何大于 0 的数字都将等待时间配置为该时间(以秒为单位)以作为事务尝试获取所需锁的指定时间段。

二、oplog 大小限制
MongoDB 会创建出与事务中写操作数量相同的 oplog 条目。但是,每个oplog 条目必须在 16MB 的 BSON 文档大小限制之内。

事务为 MongoDB 的一致性提供了一个有用的特性,但是它们应该与富文档模型结合使用。该模型的灵活性以及使用设计模式等最佳实践有助于避免在大多数情况下使用事务。事务是一个强大的特性,最好在应用程序中谨慎使用。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐