在前端开发领域,很多应用都需要使用数据库来存储数据。MongoDB 是一种常用的 NoSQL 数据库,它的快速性能和灵活性受到广泛认可。但是,MongoDB 在事务处理方面的处理一直以来备受争议。该文章将详细介绍 MongoDB 的事务处理方式,深入探讨了这种处理的优缺点,并提供一些实用的指导意义和示例代码。
MongoDB 的事务处理
如果您之前不知道,MongoDB 的文档是一个完整的 JSON 对象。因此,作为文档式数据库,之前一直被认为是无法支持事务处理。然而,自从 MongoDB 4.0 推出以来,该数据库现已支持多文档事务处理。这是 MongoDB 开始成为支持关系型数据库的首选解决方案的一个重要里程碑。
MongoDB 的事务处理使用了两阶段提交协议(2PC),这是一种常用的处理分布式事务的协议。在 MongoDB 中,事务的所有操作都必须在同一个副本集合(Replica Set)或者分片集群(Sharded Cluster)中进行。因此,事务处理是分布式的,需要有效的协议来保证原子性、一致性、隔离性、持久性。
在 MongoDB 的事务处理中,有两种类型:基于副本集合的事务处理和基于分片集群的事务处理。这两种方式都涉及到多个文档的读写操作。事务中的操作可以分为读操作和写操作。读操作不需要提交事务,但写操作需要提交事务。
四种事务的执行顺序和结果
MongoDB 中的事务处理是基于四种不同的执行顺序和结果。它们是:
- 单个操作:单个操作不需要事务而执行。我们不需要考虑提交或回滚这些操作。
- 多个独立操作:每个操作是独立的,即使其中一个操作失败也不影响其他操作。只有在事务成功提交后,所有操作的结果才会持久化并对客户端可见。
- 隐式事务:这是一个单个的写操作,它会触发事务,并将操作结果提交到数据库。
- 显式事务:显式事务是完整的事务,包括开始、提交或回滚三个步骤。这种事务必须包含有一个或多个读写操作,并且需要显式提交才能生效。
在这里,我们主要关注显式事务和其中使用的操作。
MongoDB 的事务处理的优缺点
使用事务处理在任何应用程序中都是有优缺点的。MongoDB 的事务处理也不例外。在这里我们来看看 MongoDB 的事务处理的优缺点:
优点
- 支持多文档事务:MongoDB 的事务处理支持并发读写多个文档,这意味着多个操作可以在同一个事务内提交或回滚。
- 原子性:MongoDB 的事务处理为操作序列提供了原子性保证,即使在故障情况下也不会影响数据的完整性。
- 一致性:操作会遵循事务原则,即事务不完全执行时,MongoDB 会自动回滚到标志位置,使得文档集合保持一致性。
- 隔离性:MongoDB 的事务处理提供了隔离级别。事务是在隔离级别 SERIALIZABLE 和 READ COMMITTED 下运行的。 READ COMMITTED 提供了非常高的隔离级别,但实现更简单。 SERIALIZABLE 提供了最高级别的隔离,但更加复杂和影响性能。
缺点
- 性能影响:MongoDB 的事务处理会影响系统性能,因为这需要提供更多的服务器资源来保证事务的性能和可扩展性。
- 不支持跨文档、跨集合的事务处理:在 MongoDB 的事务处理中只能处理同一副本集或分片集群中的数据。如果需要处理跨文档或跨集合的数据,需要重新设计数据的结构。
MongoDB 的事务处理示例
下面是一个使用 MongoDB 的显式事务处理的示例代码。我们将使用一个简单的账户系统,其中包含用户账户和交易信息的集合。
在这个示例中,我们将使用两个简单的文件:一个用于测试应用程序代码的文件(test.ts),另一个包含商业代码的文件(app.ts)。以下是有关于如何使用 MongoDB 的显式事务处理的示例代码:
app.ts
------ - ----------- - ---- ---------- ----- -------- -------------------- ------- --- ------- ------- ------- - ----- --- - ---------------------------- ----- ------ - --- ----------------- --- - ----- ----------------- ----- -------- - ---------------------- ----- ------- - ---------------------- --------------------------- ----- --------------- - ----------------------------- ----- -------- - ----- ------------------------- ---- ---- -- - ------- --- -- ----------- - ----- --------------------------- ----- --- ----------- ---- --- --------- --- -------- - ----- ------ - ----- ------------------------- ---- -- -- - ------- --- -- --------- - ----- --------------------------- ----- --- ----------- ---- --- ------- --- -------- - -- ---------------- - ------ - -- - ----- --------------------------- ----- --- ------------------- --------- - ----- -------------------------- - ---- ---- -- - ----- - ------- ------- - -- - ------- -- -- ----- -------------------------- - ---- -- -- - ----- - ------- ------ - -- - ------- -- -- ----- ---------------------------- ----------------------- --------- ------ ---- --------- -- ---------- - ----- --- - ----------------- - ------- - ----- --------------- - - -- -------- -- ------- ---- ---- -- --- -- ---- -- --- ----- --------------------- ------ ----
此代码使用 MongoDB 的 MongoClient
API 进行连接到数据库,默认端口(27017)。在此之后,该代码初始化了一个事务会话(session
),并开始事务处理。在后续的代码中,会第一次查询到 users
集合中的相应数据,并确保资金充足,而且必须至少有两个查询才能提交或回滚事务。
test.ts
------ - ----------- - ---- ---------- ------ - -- --- ---- -------- ----- -------- ------ - ----- --- - ---------------------------- ----- ------ - --- ----------------- --- - ----- ----------------- ----- --------------- - ------------------------------------------ -- ------ ---- ---- ---- ----- ---------------------------- - ---- ------ ------- --- -- - ---- ------ ------- -- -- --- ----- ------------------------- ------ ---- -- ----- ------- ----- -------- - ----- ------------------------- ---- ----- --- ----- ------ - ----- ------------------------- ---- ----- --- ----------------- ----- ------------------------------ --------------- ----- ---------------------------- - ----- --- - ----------------- - ------- - ----- --------------- - - ----- -------
此代码在 test()
函数中使用 MongoClient
API 连接到 MongoDB,并在 'users' 集合中插入示例数据。在此之后,它调用了从 app.ts
导入的 transferCredit()
函数。请注意,该函数没有返回值,因为它通过打印输出到控制台来展示其执行的结果。测试结束后,请将编写的代码根据测试情况进行修改。
结论
在 MongoDB 4.0 及更高版本中,显式事务处理为支持多文档事务提供了一个更可靠的方式。尽管提供事务处理是一个正确且令人惊喜的决定,但是事务处理仅适用于同一龙门阵集合或分片集群中的数据。因此,当需要处理跨多个集合或数据库的数据时,需要重新设计数据模型。
总的来说,如何有效使用 MongoDB 的事务处理取决于你的应用程序的需求。在大多数情况下,建议仅使用单个文档操作,除非必须在多个文档之间添加事务处理。因此需要权衡性能和数据一致性的影响,以确定是否使用事务。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/670f49fc5f551281026390da