使用 Mongoose 实现 MongoDB 的事务处理

阅读时长 5 分钟读完

前言

MongoDB 是一款非关系型数据库,它使用文档存储数据。与传统的关系型数据库相比,MongoDB 具有许多优点,如灵活性、可扩展性和性能等。但是,MongoDB 原本不支持事务处理,这在某些情况下限制了 MongoDB 的使用。

自 MongoDB 4.0 版本以来,官方推出了事务处理的支持。Mongoose 是一个 Node.js 的 MongoDB 驱动程序,它使 MongoDB 更容易在 Node.js 中使用。本文将介绍如何在 Node.js 中使用 Mongoose 实现 MongoDB 的事务处理。

Mongoose

Mongoose 是一个 MongoDB 驱动程序,它提供了一系列极富表现力且具有消费者友好的 API,简化了 MongoDB 的使用流程。Mongoose 还支持模式和模型,用于定义对象的属性和行为,并在 MongoDB 中创建集合。下面是一个使用 Mongoose 连接到 MongoDB 并定义模式和模型的示例:

-- -------------------- ---- -------
----- -------- - --------------------

-- ---- ------- --- --- --------
---------------- - ---------------

-- ----- ------- ---
--------------------------------------------- - ---------------- ---- ---

-- -----
----- ---------- - --- -----------------
  ----- -------
  ----- - ----- -------- -------- ----- --
---

-- -----
----- ---- - ---------------------- ------------

MongoDB 事务处理

MongoDB 事务处理使得多个操作可以作为一个原子操作一起执行。一个事务要么完全成功,要么完全失败,不存在部分失败的情况。MongoDB 的事务处理使用两段提交(Two-Phase Commit)协议,确保事务的 ACID 特性。以下是 MongoDB 的事务处理 API:

  • db.startSession(options):创建一个新的事务对象。
  • session.startTransaction(options):开启一个新的事务。
  • session.commitTransaction():提交事务。
  • session.abortTransaction():回滚事务。

对于 Mongoose 用户,我们可以使用 mongoose.startSession() 方法创建一个新的事务对象,并使用 session.withTransaction() 方法在事务内执行操作。以下是 Mongoose 的事务处理 API:

  • mongoose.startSession(options):创建一个新的事务对象。
  • session.withTransaction(fn):在事务内执行待执行的函数。

实现 MongoDB 事务处理

假设我们正在编写一个在线商店应用程序,并由以下两个集合组成:

-- -------------------- ---- -------
-- -------
----- ---------- - --- -----------------
  --------- - ----- ------- ------- ---- --
  -------- - ----- ------- -------- - --
---

-- -----
----- ----------- - --- -----------------
  --------- -------
  ------- -------
---

我们想要实现一个功能,即将用户账户余额扣减与订单金额相等的金额,并在订单集合中添加一个新的订单。在这个过程中,我们需要确保对两个集合的更改都能原子地执行。

我们可以使用 Mongoose 的事务处理来实现这个功能。下面是使用 Mongoose 的事务处理实现上述功能的示例:

-- -------------------- ---- -------
-- --------------------
----- --------------------------------------------- -- -- -
  -- -------
  ----- ---- - ----- -------------- --------- ----- --------------------

  -- -----------------
  -- ------------- - ------------- -
    ----- --- ------------------- ----------
  -

  -- ---------
  ------------ -- -------------
  ----- ----------- ------- ---

  -- -----
  ----- -------- - --- -------
    --------- --------------
    ------- -------------
  ---
  ----- --------------- ------- ---
---

在这个示例中,我们开启了一个新的事务,并使用 await session.withTransaction() 方法在事务中执行函数。在函数中,我们先查找对应的用户账户,如果用户账户余额不足,就抛出异常。如果用户账户余额充足,就将其余额扣减并保存,然后创建一个新的订单并保存。

在使用 Mongoose 的事务处理时,需要注意以下几点:

  • Mongoose 只支持在 MongoDB 4.0 及更高版本中的副本集和分片集群中使用事务处理。
  • 事务内不能执行读写操作,需要使用会话对象传递事务来调用操作。
  • 使用事务处理需要开启 MongoDB 的副本集和服务器上的分片集群,这可能会影响服务器的性能。

总结

MongoDB 的事务处理使得多个操作可以作为一个原子操作一起执行,确保事务的 ACID 特性。在 Node.js 中使用 Mongoose 实现 MongoDB 的事务处理,可以使得代码更加简单和易于维护。但是,事务处理需要开启 MongoDB 的副本集和分片集群,需要注意服务器性能。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/649e539048841e9894adb4df

纠错
反馈