随着实时应用程序和物联网 (IoT)设备的使用,加上非结构化数据资产的指数级增长,越来越多的组织正在开始采用 NoSQL 数据库。事实上,NoSQL 市场预计到 2032 年将达到 745 亿美元,从 2024 年到 2032 年的增长率(CAGR)为 24.9%(IMARC 集团,2024 年)。
鉴于 NoSQL 数据库管理系统 (DBMS) 能够有效管理大型多样化数据集以及所需的相关大数据分析,这种增长并不令人惊讶。然而,许多人仍然认为 NoSQL DBMS 无法解决许多组织的关键需求 — ACID 事务管理和合规。好消息是,某些 NoSQL DBMS 具备这种能力!
在本文中,我们将讨论什么是 ACID 事务、ACID 事务的属性、ACID 事务为何重要以及 NoSQL DBMS 中的 ACID 事务示例。
目录
从最基本的层面上来说,数据库事务是一组根据 DBMS 定义(例如,定义的事务标准)成功完成的数据库读写操作。事务主要有两种类型:
单个事务:单个事务是指一系列一个或多个数据库操作,导致一个动作,成功完成。一旦完成,事务即被接受,并可在事务日志中找到。单个事务的一个常见例子是从 ATM 机取款。
多事务:多事务,有时也称为分布式事务,由分布在不同数据库和系统(例如分布式系统)中的多个相互依赖的事务组成。这些事务的记录也可以在事务日志中找到。这些事务的例子包括将钱从一个账户转移到另一个账户,或者雇主给新员工发放带有照片的安全徽章。
请务必注意,某些事务需要遵守严格的数据完整性(例如,数据完整且正确)和数据一致性(例如,所有表/数据库中的值相同)标准。这通常包括涉及受托责任或监管合规的情况。例如商业银行业务、投资经纪业务和法律和解。在这些情况下,仅仅遵守 DBMS 定义的标准是不够的,还需要符合 ACID 事务要求。
ACID 是原子性、一致性、隔离性和持久性(ACID)的缩写。ACID 属性共同确保了一组数据库操作(在事务中组合在一起)即使在出现意外错误时也能使数据库处于有效状态。此外,ACID 事务提供了许多监管机构要求的 ACID 一致性保证级别。
下面提供了每个 ACID 事务元素的简要概述,以及 NoSQL 文档数据库如何处理相应 ACID 元素的说明。本文将使用 MongoDB Atlas。
原子性保证组成事务的所有命令都被视为一个单元,要么一起成功,要么一起失败。这一属性在系统故障或断电时非常重要,因为如果一个事务没有完全处理完成,它就会被舍弃,数据库就能保持数据的完整性。
在 MongoDB 中,写入操作在单个文档级别上是原子性的,即使该操作修改单个文档中的多个嵌入文档也是如此。对于需要对多个文档(在单个集合或多个集合中)的读写操作具有原子性的情况,MongoDB 支持分布式事务,包括副本集和分片集群上的事务。
####一致性
一致性保证在 ACID 事务中所做的更改填充到数据库系统(例如节点)中,并与 DBMS 约束保持一致。如果处于不一致状态的 ACID 事务对数据一致性产生负面影响,则整个 ACID 事务将失败。
MongoDB 可以灵活地规范化或复制数据,从而优化应用程序。如果模式中存在重复数据,则开发人员必须决定如何在多个集合中保持重复数据的一致性。一些应用程序需要立即使重复的数据保持一致,而其他应用程序可以容忍读取过时数据。示例如下所示:
注意:了解有关[数据一致性]的更多信息。
每个事务都与其他事务隔离,以防止数据冲突。这还有助于与管理多个条目和多级事务相关的数据库操作。例如,如果两个用户试图修改相同的数据(甚至是同一个事务),DBMS 会使用一种称为锁管理器的机制来暂停其他用户,直到第一个用户所做的更改完成为止。
MongoDB 采用一种称为快照隔离的技术(例如,每个事务似乎都在事务开始时拍摄的数据库的个人快照上运行)。事务可以从事务开始时提交的数据的“快照”中读取数据,任何冲突的更新都将导致事务中止。
此外,MongoDB 事务支持事务级读关注 以及事务级别的写关注。客户端可以设定适当的读关注和写关注级别,其中最严格的是将快照读关注与大多数写关注点相结合。大多数写关注意味着写入操作已持久性地提交给计算出的大多数数据承载节点(可由开发人员配置)。
持久性保证,一旦事务完成并将更改写入数据库,它们就会持续存在。这样可以确保即使在系统故障(例如崩溃或服务中断)的情况下,系统内的数据也将持久存在。持久性的概念是数据可靠性的关键要素。
MongoDB 创建一个 OpLog,其中包含每次“写入”的磁盘位置和更改的字节。如果在写入事务期间发生不可预见的事件(例如停电),则可以在系统重新启动时使用 OpLog 来重放关机前未刷新到磁盘的所有写入操作。此外,操作在写入 OpLog 之前会被更改,因此它们具有幂等性,可以多次重试。默认情况下,事务或“写入”大约每 60 秒刷新到磁盘一次。
ACID 事务有助于保持数据的完整性和可靠性,同时确保受政府或行业监管的重要数据(如银行账户、股票投资组合)符合所需标准。此外,ACID 合规性通常是在分布式数据库系统中实现数据复制和实现高可用性的先决条件。
此示例使用 NoSQL 文档数据库 MongoDB Atlas,演示了如何处理 ACID 多文档事务以及 ACID 事务如何保证与最低 ACID 属性标准一致。
想象一下,您正在构建一项从一个银行账户向另一个银行账户转账的功能,其中每个账户都有自己的记录。如果从源账户成功提取了资金,但却从未将其记入目标账户,就会产生严重的会计问题。相反,如果存入目标账户但从未从源账户中扣款,则会出现另一个严重的会计问题。
该图演示了 ACID 属性如何影响将资金从一个银行账户转移到另一个银行账户的流程。
这两个写入操作必须同时发生或同时不发生,才能保持系统及其数据的一致。此外,这意味着如果ACID 事务中的任何命令失败,则数据库必须回滚(例如,撤消)其在 ACID 事务过程中写入的所有更改。
注意:要了解更多信息,请访问 Node.js 快速入门 GitHub 存储库,获取完整代码示例的副本并自行运行。
在分布式系统中处理多文档事务时,请记住存在性能开销影响,这可能会影响资源限制和性能目标。此外,由于数据库必须“锁定”相关资源以防止并发写入相互干扰(例如,事务失败),因此尝试写入数据的其他客户端可能会等待事务完成,这可能会影响应用程序延迟和用户体验。
MongoDB 的文档模型允许将相关数据一起存储在单个文档中。文档模型与原子文档更新相结合,在大多数使用案例中消除了对事务的需要。尽管如此,在某些情况下,真正的多文档、多集合 MongoDB 事务才是最佳选择。
MongoDB 事务的工作方式与其他数据库中的事务类似。要使用 ACID 事务,请通过驱动程序启动 MongoDB 会话。然后,使用该会话执行群组数据库操作。您可以跨多个文档、集合和分片运行任何 CRUD(创建、读取、更新和删除)操作。
有关如何实施事务的具体代码样本,请查看 MongoDB 开发人员中心的快速入门:
访问 MongoDB 驱动程序文档,查看 MongoDB 正式支持的每种语言的具体指南。您还可以查看事务最佳实践和生产注意事项列表。
需要事务的应用程序通常具有在不同方之间交换值的用例。这些通常是“记录系统”或“业务线”应用程序。
可能从多文档事务中受益的示例应用程序包括:
一般来说,建议对数据进行建模,以便将一起数据访问的数据存储在一起。以这种方式建立数据模型后,不仅可以获得更好的性能,而且无需进行事务处理。
对于需要事务的应用程序,请遵循以下最佳实践:
将长时间运行的事务分成较小的部分,这样它们就不会超过默认的 60 秒超时。(请注意,此超时时间可以延长。)确保事务中的操作使用索引,以便快速运行。
将每个 ACID 事务限制为 1,000 项文档修改。
确保已配备适当的 写关注(请注意,从版本 5.0 开始, MongoDB 默认为必要的多数写关注)。
添加适当的错误处理,并重试由于暂时性错误而失败的事务。
记住影响多个分片的事务的性能费用。 有关这些最佳实践的更多信息,请查看 MongoDB 上的多文档 ACID 事务白皮书以及有关事务的 MongoDB 文档。
准备好了解更多信息了吗?MongoDB Atlas 是 MongoDB 的完全托管数据库即服务,也是开始使用 MongoDB 的最便捷方法。通过创建免费的 MongoDB Atlas 集群,开始使用事务。