gpt4 book ai didi

mysql - 升级 Knex 后出现 "Timeout acquiring a connection"

转载 作者:行者123 更新时间:2023-12-03 09:42:29 26 4
gpt4 key购买 nike

在我的公司,我们的应用程序在 NodeJS 上运行,运行在多个 EC2 实例和一个 RDS 数据库上。

我们的应用程序需要一些升级,因为一些依赖项已经很旧了,我们所做的引起我们注意的升级之一是更新我们的数据库库:mysql(从 2.16.0 到 2.17.0)、knex(从 0.12.2 到 0.19 .1) 和书架(0.10.2 至 0.15.1)。

检查更改日志后,不需要更改代码,因此我们很快设法将其上传到我们的临时服务器。

突然,我们的应用程序变得太慢了。加载所有数据需要几秒钟,而我们的主要用户的仪表板在几毫秒内加载到同一台服务器上,需要大约 30 秒。几分钟后,整个应用程序完全没有响应。

为了检查问题是否仅与依赖项升级有关,我们设法将这些降级到工作版本,并且应用程序恢复到正常速度。又升级了,又慢了。

我们已经开始通过 New Relic 分析 RDS 方面是否有问题。什么都没有。没有高峰,没有高 CPU 使用率,没有慢查询或其他任何事情。然后我们来检查连接池,发现适合我们的knex版本使用“generic-pool”,而新版本使用“tarn”。

所以我们开始调试池,发现它被指定的查询填满,完全卡住了一段时间,然后开始抛出“TimeoutError: Knex: 获取连接超时。池可能已满”错误。

但是关于填充所有池并卡住的查询最有趣的是它根本不应该生成(并且在使用不存在此问题的过时版本时不会生成)。

enter image description here

在我们的应用程序中,我们只在两种情况下对联系人表执行 SELECT 请求:

首先,很明显,当用户想要列出他们的联系人时:

let contacts = await Contacts.forge({ 'list_owner': udata.id }).fetchAll()

其次,在检查联系人匹配以判断某些信息是否应该对指定用户可见时,取决于信息所有者的隐私设置:
let checkContact = await Contacts.where({
list_owner: target_user,
contact: udata.id
}).fetch()

经过几次 grepping,我可以保证我们的代码库中没有其他地方可以从联系人表中进行 SELECTS。在我们的调试中,我们没有发现未定义的值,并且我们的调查显示查询在之前的代码运行时运行。但是正如您在屏幕截图中看到的,查询 knex 运行没有条件:
select `contacts`.* from `contacts`

我们相信这就是它填满池的原因(因为请求每个用户的联系人是一项艰巨的工作),但同时,我们不明白为什么 knex 运行这样的查询,如:
  • knex 升级后没有进行任何代码更改
  • 使用旧版 knex 时不存在此问题(我们的生产服务器使用过时的 knex 版本启动并运行)
  • 我们使用 Redis 进行了大量缓存(但无论如何,数据库不会过载并且旧的 Knex 版本可以正常工作)
  • 如果问题确实是条件缺失,我们本可以在之前发现它,因为每个用户都会看到相同的联系人列表。

  • 什么可能导致这样的问题?

    最佳答案

    执行查询后,您必须销毁连接。

     var knex = new Knex(config)
    knex(table)
    .where({ id: 1 })
    .then((result) => {
    callback(output)
    })
    .catch((err) => {
    err.error = true
    callback(err)
    })
    .finally(() => {
    knex.destroy()
    })
    })

    关于mysql - 升级 Knex 后出现 "Timeout acquiring a connection",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57263276/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com