Mongoose 中的事务处理:保证多个操作的原子性

阅读时长 5 分钟读完

前言

在开发中,经常需要进行多个操作,例如关联的数据更新、统计信息的计算等。当这些操作需要保证原子性时,需要使用事务处理,即一组多个操作要么全部成功,要么全部失败。Mongoose 是 Node.js 中操作 MongoDB 数据库的框架,提供了方便的事务处理方式,下面将介绍 Mongoose 中的事务处理。

Mongoose 中的事务处理

Mongoose 从 5.0 版本开始支持事务处理。具体实现使用 MongoDB 4.0 引入的事务处理。Mongoose 中使用事务处理的一个关键概念是会话(Session)。会话是在 Mongoose 和 MongoDB 之间的桥梁,它允许我们跨多个操作共享事务上下文。

Mongoose 中通过在 Schema 中使用 transaction: true 来开启事务处理。在事务中,我们尝试执行一组操作,并在这些操作之间维护原子性。如果这些操作中的任何一个失败,所有操作都会回滚,也就是之前执行过的所有操作都会撤销。最终结果是,所有事务内的操作要么都成功,要么都失败。

关于事务的概念可以看阮一峰老师的博客:数据库事务教程

下面看一下 Mongoose 中的事务处理详细说明。

1. 开始事务

使用 Mongoose 进行事务处理,首先需要开启会话(Session)。我们可以通过调用 mongoose.startSession() 创建一个会话。如下所示:

创建完成后,我们可以在此会话上执行各种操作,这些操作可以共享事务上下文。接下来,我们调用 session.startTransaction() 开始事务。如下所示:

这样,我们就成功开启了一个 Mongoose 事务。

2. 向事务中添加操作

现在,我们已经成功开启了一个 Mongoose 事务,下面可以向其中添加一些操作了。在事务中执行任何操作都如同普通操作一样,只是在执行时需要传入会话对象。以更新一个用户数据为例,如下所示:

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

为了在事务中执行操作,我们需要将会话对象作为 options 参数传递给操作(即上例中的 session)。

这些操作的类型可以是任何类型,包括插入、更新、删除等。

3. 发起提交或回滚

在事务完成时,我们需要提交或回滚事务。提交意味着所有操作都成功完成,而回滚意味着所有操作都失败了。Mongoose 中,分别使用 session.commitTransaction()session.abortTransaction() 发起提交或回滚。

至此,我们已经完成了 Mongoose 中的事务处理,具体实现代码可以参考下面的示例。

示例代码

下面是一个简单的示例代码,展示了如何使用 Mongoose 进行事务处理。

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

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

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

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

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

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

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

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

注意,由于 MongoDB 不支持跨两个或更多分片的事务,所以必须在同一分片上执行事务。如果要在多个分片之间执行事务,则必须将分片集合到副本集或分片集群中。

总结

Mongoose 从 5.0 版本开始支持事务处理。事务中的操作可以保证原子性,也可以统一提交或回滚操作。使用起来非常方便,它的应用范围广泛。在多个操作之间确保原子性时,事务处理非常有用。希望本篇文章对您有所启示。

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

纠错
反馈