findOne 无限期挂起(旧版本不会)

问题描述 投票:0回答:1

从事大型项目。几十个集合,每天 100 万用户,每秒 10,000+ 数据库事务。

我们只需将 Mongoose 的更新从 8.4.5 回滚到 8.2.0。 这会回滚许多其他软件包,包括转到旧版本的 mongodb、bson 等。

但这种行为是如此破坏,我找不到类似问题的任何其他报告,我正在寻找有关来源的提示。

虽然我怀疑这个

findOne
挂起发生在多个地方,但有一个明确的地方,因为我们跟踪同时处理的玩家查找数量。它挂在这里,从来没有撞到
finally
。没有例外,只是挂了。也不是每次都是。它运行约 1 小时后开始挂起(因此我怀疑连接池超出或连接被回收)。

let player: DBPlayer | null;
    try {
      this.precheck++;
      player = await models.Player.findOne({
        _id: playerId, // playerId is a string representation of an ObjectId
      })
        .select({
          _id: 1, // not necessary, but for clarity
          authId: 1, // the only field we need
        })
        .lean(); // lean does a different code path in mongoose, so might be relevant
    } finally {
      this.precheck--;
    }

在 8.4.5 大约一个小时后,我们看到我们的

precheck
数字缓慢上升,迅速增加,然后看起来稳定,然后再次爆发式上升。当然,发生的情况是我们的用户正在连接,但连接超时或者他们永远等待,因此他们刷新并重试。每次......都会在这里创建一个新的承诺并永远等待。即使超过30分钟,数字也不会下降。

models.Player
的创建方式如下:

models.Player = model<DBPlayer>('Player', schema)

模式不应该是相关的,但它相当复杂,包含映射、数组、分层对象等。所有这些都适用于 8.2.0

我怀疑这与创建新连接时的缓冲有关,但我在 mongoose 代码库中找不到在这些版本之间发生更改的代码。 文档表明缓冲就在初始连接之前,这肯定是成功的,因为我们正常运行了一个小时。

一个小时可能是回收连接的默认值,在这种情况下,它确实不起作用。

mongodb mongoose
1个回答
0
投票

删除使用同一会话进行并行查询的情况解决了该问题。该行为是明确“未定义”的,虽然它在早期的 mongo 版本中有效,但它不再有效并破坏连接状态。

底线,绝对不要使用同一会话进行并行查询!

© www.soinside.com 2019 - 2024. All rights reserved.