公告推出MongoDB 8.0,史上最快的MongoDB!了解更多 >>推出MongoDB 8.0,史上最快的MongoDB!>>

数据库管理系统中的ACID属性指南

随着实时应用程序和物联网(IoT)设备的使用,以及非结构化数据资产指数级增长,越来越多的组织正在转向NoSQL数据库。实际上,预计到2032年,NoSQL市场将达到745亿美元,从2024年到2032年的增长率(复合年增长率)为24.9%(IMARC集团,2024年)。

鉴于NoSQL数据库管理系统(DBMS)能够有效管理大型、多样化的数据集以及相关的大数据分析,这一增长并不令人惊讶。然而,许多人仍然认为NoSQL DBMS无法满足许多组织的关键需求——ACID事务管理和合规性。好消息是,一些NoSQL DBMS确实可以做到这一点!

在本文中,我们将讨论ACID事务是什么,ACID事务属性,为什么这些事务很重要,以及NoSQL DBMS中的ACID事务示例。


目录

什么是ACID事务?


事务解释

在最基本层面上,数据库事务是一组数据库读和写操作,这些操作已经根据DBMS的定义成功完成(例如,定义的事务标准)。主要有两种类型的交易

  • 单笔交易:单笔交易是指一系列一个或多个数据库操作,导致一个动作成功完成的操作序列。一旦完成,该交易将被接受,并可在交易日志中找到。单笔交易的常见例子是从ATM取款。

  • 多笔交易:多笔交易,有时称为分布式交易,由多个相互依赖的交易组成,这些交易分布在不同的数据库和系统(例如,分布式系统)中。这些交易的记录也存在于交易日志中。这些交易的例子包括从一个账户向另一个账户转账或雇主为新员工发放带有照片的安全徽章。

需要注意的是,一些交易必须遵守严格的数据完整性(例如,数据是完整和正确的)和数据一致性(例如,值在所有表/数据库中相同)标准。这种情况通常涉及信托责任或合规性。例子包括商业银行、投资经纪和法律结算。在这些情况下,仅仅遵守DBMS定义的标准是不够的,需要ACID事务。

ACID事务

ACID代表原子性、一致性、隔离性和持久性(ACID)。ACID属性共同确保即使在发生意外错误的情况下,一组数据库操作(在事务中组合在一起)也能使数据库处于有效状态。此外,ACID事务提供了许多监管机构要求的交易保证级别。

以下是对每个ACID事务元素的概述,以及NoSQL文档数据库如何处理这些ACID元素的描述。为了本文的目的,将使用MongoDB Atlas


原子性

原子性保证事务中的所有命令作为一个单一单元处理,要么全部成功,要么全部失败。这在系统故障或断电的情况下很重要,如果交易没有完全处理,则将被丢弃,数据库将保持其数据完整性。


MongoDB如何处理原子性

在MongoDB中,写操作在单个文档级别上是原子的,即使该操作修改了一个文档内的多个嵌入式文档。对于需要读取和写入多个文档的原子性(在单个集合或多个集合中)的情况,MongoDB支持分布式事务,包括对副本集和分片集群的事务。


一致性

一致性保证事务中做出的更改在整个数据库系统(例如,节点)中填充,并且与DBMS约束一致。如果交易在不一致的状态下会负面影响数据一致性,则整个交易将失败。

MongoDB如何处理一致性

MongoDB提供灵活的数据规范化或复制的选项来优化应用程序。如果数据在模式中被复制,开发人员必须决定如何保持多个集合中复制的数据一致性。某些应用程序需要立即使复制的数据保持一致,而其他应用程序可以容忍读取陈旧的数据。以下是一些示例

方法描述性能影响用途
事务多个集合的更新发生在单个原子操作中由于读竞争,可能很高您的应用程序必须始终返回最新的数据,并且可以在高读取期间容忍潜在的性能影响。
嵌入相关数据修改应用程序模式,将相关数据嵌入到单个集合中。根据文档大小和索引,低到中等您的应用程序始终同时读取和更新相关数据。此解决方案简化了您的模式,并防止了需要对$lookup操作的需求。
Atlas数据库触发器当一个集合发生更新时,触发器会自动更新另一个集合。低到中等,存在处理触发事件的可能延迟您的应用程序可以容忍读取略微过时的数据。如果用户在更新后立即运行查询,但在触发器完成更新第二个集合之前,用户可能会看到过时的数据。

方法

描述
事务多个集合的更新发生在单个原子操作中
嵌入相关数据修改应用程序模式,将相关数据嵌入到单个集合中。
Atlas数据库触发器当一个集合发生更新时,触发器会自动更新另一个集合。
性能影响
事务由于读竞争,可能很高
嵌入相关数据根据文档大小和索引,低到中等
Atlas数据库触发器低到中等,存在处理触发事件的可能延迟
用途
事务您的应用程序必须始终返回最新的数据,并且可以在高读取期间容忍潜在的性能影响。
嵌入相关数据您的应用程序始终同时读取和更新相关数据。此解决方案简化了您的模式,并防止了需要对$lookup操作的需求。
Atlas数据库触发器您的应用程序可以容忍读取略微过时的数据。如果用户在更新后立即运行查询,但在触发器完成更新第二个集合之前,用户可能会看到过时的数据。

注意:了解更多关于数据一致性的信息。


隔离性

每个事务与其他事务隔离,以防止数据冲突。这也有助于数据库操作,涉及管理多个条目和多级事务。例如,如果两个用户试图修改相同的数据(甚至相同的交易),DBMS使用称为锁管理器的机制来暂停其他用户,直到第一个用户所做的更改完成。


MongoDB如何处理隔离性

MongoDB采用了一种称为快照隔离的技术(例如,每个事务似乎在事务开始时对数据库的个人快照进行操作)。事务可以从事务开始时提交的“快照”数据中读取数据,任何冲突的更新都将导致事务中止。

此外,MongoDB事务支持事务级读取关注事务级写入关注。客户端可以设置适当的读取和写入关注级别,最严格的是快照读取关注与多数写入关注的组合。多数写入关注意味着写入操作已持久地提交到计算出的多数数据承载节点(由开发者配置)。


持久性

持久性保证一旦事务完成并将更改写入数据库,它们就会持久化。这确保了即使在系统故障(如崩溃或断电)的情况下,系统中的数据也将持续存在。持久性的概念是数据可靠性的关键要素。


MongoDB如何处理持久性

MongoDB创建一个OpLog,其中包含每个“写入”的磁盘位置和字节更改。如果在写入事务期间发生不可预见的事件(例如断电),则在系统启动时可以使用OpLog重放任何在关闭之前未刷新到磁盘的写入。此外,操作在OpLog中更改后再写入,以便它们是幂等的,可以重试多次。默认情况下,事务或“写入”每60秒大约刷新到磁盘一次。

为什么ACID事务很重要?

ACID事务有助于维护数据完整性和可靠性,同时确保受政府或行业规范约束的关键数据(例如,银行账户、股票组合)符合要求标准。此外,ACID兼容性通常是实现数据复制和在分布式数据库系统中实现高可用性的先决条件。

DBMS中的ACID事务示例

使用NoSQL文档数据库MongoDB Atlas,以下是一个如何处理ACID多文档事务以及ACID事务如何保证符合最小ACID属性标准的示例。

ACID多文档事务

假设您正在构建一个功能,用于将资金从一个银行账户转移到另一个账户,其中每个账户都是一个单独的记录。如果资金成功从源账户扣除但从未贷记到目标账户,就会产生严重的会计问题。相反,如果目标账户已贷记但源账户从未扣除,则会出现另一个严重的会计问题。


展示如何通过ACID属性影响从银行账户之间转账流程的图。 该图展示了ACID属性如何影响银行账户之间转账的流程。


这两个写操作必须同时发生或同时不发生,以保持系统和其数据的一致性。此外,这意味着如果事务中的任何命令失败,数据库必须回滚(例如,撤销)它在事务过程中写入的所有更改。


code sample from github in partnership with mongodb

注意:要了解更多信息,请访问Node.js 快速入门 GitHub 仓库以获取完整代码示例并自行运行。


需要记住的影响

在处理分布式系统中的多文档事务时,请记住,性能开销可能会影响资源约束和性能目标。此外,由于数据库必须“锁定”所涉及的资源以防止并发写入相互干扰(例如,事务失败),尝试写入数据的其他客户端可能会因等待事务完成而受阻,这可能会影响应用程序延迟和用户体验。

MongoDB中ACID事务的工作方式

MongoDB的文档模型允许相关数据在单个文档中存储。文档模型与原子文档更新相结合,消除了在大多数用例中需要事务的需求。尽管如此,在某些情况下,真正的多文档、多集合MongoDB事务是最佳选择。

MongoDB事务的工作方式与其他数据库中的事务类似。要使用事务,通过驱动程序启动MongoDB会话。然后,使用该会话执行您的数据库操作组。您可以在多个文档、集合和分片中运行任何CRUD(创建、读取、更新和删除)操作。

有关实现事务的特定代码示例,请查看MongoDB开发者中心的快速入门教程。

请访问MongoDB驱动程序文档,获取MongoDB官方支持的每种语言的特定指南。您还可以查看事务最佳实践和生产注意事项列表

我应该何时使用MongoDB多文档事务?

需要事务的应用程序通常涉及不同实体之间的值交换。这些通常是“记录系统”或“业务线”应用程序。

可能从多文档事务中受益的应用程序示例包括

  • 将资金从一个账户转移到另一个账户的系统(例如,银行应用程序、支付处理系统、交易平台)。

  • 供应链和预订系统,其中商品和服务所有权从一个实体转移到另一个实体。

  • 计费系统,用于存储详细信息记录以及汇总记录。

MongoDB事务的最佳实践是什么?

通常建议以这种方式建模数据,以便一起访问的数据存储在一起。以这种方式建模数据时,不仅可以获得更好的性能,而且不需要进行事务。

对于确实需要事务的应用程序,请遵循以下最佳实践

  • 将长时间运行的事务分解成更小的部分,以避免超过默认的60秒超时。(注意,此超时可以扩展。)确保事务中的操作正在使用索引,以便它们快速运行。

  • 将每个事务限制在1,000个文档修改内。

  • 确保已配置适当的读写关注点(请注意,从版本5.0开始,MongoDB默认为必要的多数写关注点默认设置)。

  • 添加适当的错误处理并重试由于暂时性错误而失败的交易。

  • 记住事务影响多个分片时的性能成本。有关这些最佳实践的更多信息,请参阅MongoDB的多文档ACID事务白皮书以及MongoDB事务文档。

下一步

想要了解更多吗? MongoDB Atlas是MongoDB的完全托管数据库服务,它是开始使用MongoDB的最简单方法。通过创建免费的MongoDB Atlas集群开始使用事务。

常见问题解答

什么是多文档事务?

多文档事务,有时称为分布式事务,是由多个相互依赖的事务组成的,这些事务分布在不同的数据库和系统中。

什么是ACID事务?

ACID事务是一组数据库系统中的操作,它与ACID属性一致。

事务的ACID属性是什么?

ACID的四个关键属性是原子性、一致性、隔离性和持久性。