【问题标题】:Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?Knex:获取连接超时。游泳池可能已经满了。你错过了一个 .transacting(trx) 电话吗?
【发布时间】:2023-03-14 01:30:01
【问题描述】:

我正在使用以下代码进行knex连接,但经常出现错误

Knex:获取连接超时。游泳池可能已经满了。你错过了一个 .transacting(trx) 电话吗?

谁能建议这个问题的解决方案?

var knexConn = reqKnex({
        client: pClient,
        native: false,
        connection: pConn,
        searchPath: pSearchPath,
        pool: {
            max: 7,
            min: 3,
            acquireTimeout: 60 * 1000
        }
    });


function getTransactionScope(pKnex, callback) {
    try {
        pKnex.transaction(function(trx) {
            return callback(trx);
        });
    } catch (error) {
        console.log(error);
    }
}

function ExecuteSQLQuery(pTranDB, pTrx, pQuery, pCallback) {
    try {
        var query = pTranDB.raw(pQuery);

        if (pTrx) {
            query = query.transacting(pTrx);
        }
        query.then(function(res, error) {
            try {
                if (error) {
                    console.log(error);
                } else {
                    return pCallback(res, error);
                }
            } catch (error) {
                console.log(error);
            }
        }).catch(function(error) {
            return pCallback(null, error);
        });
    } catch (error) {
        console.log(error);
    }
}

function Commit(pTrx, pIsCommit) {
    try {
        if (pIsCommit) {
            pTrx.commit();
        } else {
            pTrx.rollback();
        }
    } catch (error) {
        console.log(error);
    }
}

【问题讨论】:

  • 是否你有.transacting(trx)(或关闭)电话(动态)?)
  • 你有想过这个问题吗?
  • 谁能解决这个错误?
  • 有人找到这个错误的解决方案吗?
  • 不要使用propagationError: false github.com/knex/knex/issues/3455

标签: node.js knex.js


【解决方案1】:

我用这些版本解决了这个问题:

"knex": "^0.21.1",
"objection": "^2.1.3",
"pg": "^8.0.3"

【讨论】:

  • 这很有帮助:更新到这些版本解决了我的问题。显然,节点 14 刚出来并破坏了 knex 或 pg 驱动程序或某处的某些东西......连接失败,你得到的只是Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?
  • 在节点 14 + pg 8.0.2 中遇到此问题。将 pg 更新到 8.0.3 解决了我的问题!
  • thx @ddriver1 为我节省了很多时间。我只更新了pg,问题就解决了。
  • 知道为什么这些版本解决了@bratislav 的问题吗?
【解决方案2】:

我最近遇到了这个问题,我刚刚更新到 Node v14.2.0

此版本似乎对 knex 进行了重大更改。幸运的是我有 NVM,所以我切换到另一个版本(v12.16.3),这解决了这个问题。

祝你好运!

【讨论】:

  • 确认了这一点。我在节点 14.4.0 上,然后使用 nvm 移回 12.14.1(选择了队友正在使用的版本),一切都很好。
【解决方案3】:

当我升级到节点14.0.0 时,我也遇到了这个问题。我恢复了我的节点版本,这个问题就消失了。

【讨论】:

  • 我也确认了!我以前经历过!在跟踪唯一的变化是升级节点后,我用 nvm 更改了版本!它奏效了!这次又忘记了hhhh!这让我想起了!
【解决方案4】:

在将一个 Strapi 应用程序部署到 heroku 时,我遇到了同样的问题。 在我的 package.json 中,我有以下版本:

  • "knex": "<0.20.0"
  • "pg": "^7.18.2"

我还有以下节点引擎配置:

"engines": {
  "node": ">=10.0.0",
  "npm": ">=6.0.0"
},

将版本更改为<0.21.1^8.0.3(此处建议:https://stackoverflow.com/a/61482183/4696783)并将节点引擎更改为12.16.x(此处建议:https://stackoverflow.com/a/61942001/4696783)解决了该问题。

【讨论】:

    【解决方案5】:

    对于遇到此问题的任何其他人,这也可能是由于您的数据库主机名中的拼写错误(我就是这种情况)。

    【讨论】:

      【解决方案6】:

      属性 propagateCreateError 应设置为 false 以防止超时获取连接。游泳池可能已经满了。你错过了一个 .transacting(trx) 电话吗?错误。

      示例池配置:

      "pool": {
        "min": 2,
        "max": 6,
        "createTimeoutMillis": 3000,
        "acquireTimeoutMillis": 30000,
        "idleTimeoutMillis": 30000,
        "reapIntervalMillis": 1000,
        "createRetryIntervalMillis": 100,
        "propagateCreateError": false // <- default is true, set to false
      },
      

      说明propagateCreateError 在 Knex 中默认设置为 true 并在第一次创建与数据库的连接失败时抛出 TimeoutError,防止 tarn(连接池管理器)自动重新连接。

      解决方案是将 propagateCreateError 设置为 false,从而使 knex 在创建连接失败时自动重新连接,而不是抛出错误。

      极光数据库: 如果你正在连接一个 AuroraDB 实例,目前它的启动时间很长,每次新冷启动都会导致 TimeoutError,为了解决这个问题,设置 AWS Console -> RDS -> AuroraDB Instance -> Pause compute capacity after continuous不活动分钟数:1440 小时以防止数据库完全进入休眠状态。

      详细解释请看 https://github.com/knex/knex/issues/2820

      【讨论】:

        【解决方案7】:

        我做了一些测试。结果如下。

        "knex": "^0.20.8",
        "objection": "^2.1.2",
        "pg": "^7.14.0"
        

        使用这些版本,我的应用在节点 12.22.7 上运行良好,但在 14.18.1 上出现超时问题。

        pg 更新到版本8.0.2

        • 12.22.7 -> 工作正常
        • 14.18.1 -> knex 超时错误

        pg更新到版本8.0.3

        • 12.22.7 -> 工作正常
        • 14.18.1 -> 工作正常

        pg 版本为8.0.3 时,节点14 上的问题消失了。

        【讨论】:

        • 在某些情况下,增加超时时间会有所帮助。尝试在 knex 中设置 acquireConnectionTimeout(比如 50*1000)
        • 这应该是被接受的答案。它也适用于节点 v16.13.1。
        【解决方案8】:

        我必须修补 knex npm 包以至少重试一次获取池连接,然后再抛出错误以防 knex 超时问题。打开文件node_modules/knex/lib/client.js。你会看到这个方法:

          async acquireConnection() {
            if (!this.pool) {
              throw new Error('Unable to acquire a connection');
            }
            try {
              const connection = await this.pool.acquire().promise;
              debug('acquired connection from pool: %s', connection.__knexUid);
              return connection;
            } catch (error) {
              let convertedError = error;
              if (error instanceof TimeoutError) {
                convertedError = new KnexTimeoutError(
                  'Knex: Timeout acquiring a connection. The pool is probably full. ' +
                    'Are you missing a .transacting(trx) call?'
                );
              }
              throw convertedError;
            }
          },
        

        替换为:

        async acquireConnection() {
            if (!this.pool) {
              throw new Error('Unable to acquire a connection');
            }
            try {
              const connection = await this.pool.acquire().promise;
              debug('acquired connection from pool: %s', connection.__knexUid);
              return connection;
            } catch (error) {
              this.logger.warn('Acquire connection error, retrying once');
              try {
                if (!this.pool) {
                  this.logger.warn('Pool has been destroyed, initializing again');
                  this.initializePool();
                }
                const connection = await this.pool.acquire().promise;
                debug('acquired connection from pool: %s', connection.__knexUid);
                return connection;
              } catch (error) {
                let convertedError = error;
                if (error instanceof TimeoutError) {
                  convertedError = new KnexTimeoutError(
                    'Knex: Timeout acquiring a connection. The pool is probably full. ' +
                      'Are you missing a .transacting(trx) call?'
                  );
                }
                throw convertedError;
              }
            }
          },
        

        然后打补丁

        yarn add -D patch-package
        yarn patch-package knex
        

        然后创建一个postinstall npm 脚本,以便在每次安装后自动运行:

        "postinstall": "patch-package -p1 -i patches/<name of your patch file>"
        

        PS:使用节点v14.17.6

        【讨论】:

          【解决方案9】:

          在我的应用程序中,我面临着(有时介于两者之间)

          TimeoutError: Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?
          

          我的 knex 配置是

          const config = client: process.env.CLIENT,
            connection: {
              host: process.env.DBHOST,
              user: process.env.DBUSER,
              password: process.env.DBPASS,
              database: process.env.DATABASE
            },
            pool: { min: 0, max: 30, acquireTimeoutMillis: 60 * 1000 },
            seeds: {
              directory: './db/sds'
            },
            migrations: {
              directory: './db/mg'
            }
          }
          
          import knexLib from 'knex';
          export const con = knexLib(config);
          
          

          我正在使用类似的东西

          import {con} from './con';
          import {FormatError} from '../err'
          
          const handler = (req)=>{
            const trx = con.transaction();
            try{
              const result = await con('insert-table').transacting(trx).insert(req.list).returning('*');
              const resultOfLog = await Promise.all(
                result.map((o) => {
                  return con('log-table')
                    .insert({event_id: 1, resource: o.id});
                  })
              );
              return result;
            } catch(error){
              return new FormatError(error);
            }
          }
          
          

          【讨论】:

            【解决方案10】:

            如果您在代理后面工作,则可能会发生此错误,因为您在命令行中的代理配置不正确。验证 envs http_proxy, https_proxy 如果你的 SO 是 linux。

            【讨论】:

              【解决方案11】:

              从节点 v12.16.1 迁移到 v14.18.1 时我遇到了同样的问题(目前是最新的 14 个)。 解决问题的步骤:

              • bump knex 版本=0.20.1 --> 0.95.11
              • bump pg 版本7.12.1 --> 8.7.1
              • 删除 knex-migrate 模块并通过原始 knex 进行迁移
                     const [totalMigrations, executedMigrations] = await knex.migrate.up({
                         directory: require('path').resolve(__dirname, 'migrations'),
                         disableMigrationsListValidation: true, 
                     });
                     logger.info('Migration success', { totalMigrations, executedMigrations });
              

              【讨论】:

                【解决方案12】:

                我有同样的问题, 考虑到: this post.

                propagateCreateError 属性应设置为 false 以防止超时 获取连接。游泳池可能已经满了。你错过了一个 .transacting(trx) 电话吗?错误。

                示例池配置:

                “池”:{ “分钟”:2, “最大”:6, “createTimeoutMillis”:3000, “acquireTimeoutMillis”:30000, “idleTimeoutMillis”:30000, “reapIntervalMillis”:1000, “createRetryIntervalMillis”:100, "propagateCreateError": false //

                propagateCreateError 在 Knex 中默认设置为 true,如果与数据库的第一次创建连接失败,则会引发 TimeoutError,从而防止 tarn(连接池管理器)自动重新连接。

                解决方案是将propagateCreateError 设置为false,从而使knex 在创建连接失败时自动重新连接,而不是抛出错误。

                this post:

                我做了如下配置

                module.exports = {
                    client: 'pg',
                    connection: {
                        host: config.testDB.host,
                        user: config.testDB.userName,
                        port: config.testDB.port,
                        password: config.testDB.password,
                        database: 'testdb',
                        charset: 'utf8'
                    },
                    pool: {
                        max: 50,
                        min: 2,
                        // acquireTimeout: 60 * 1000,
                        // createTimeoutMillis: 30000,
                        // acquireTimeoutMillis: 30000,
                        // idleTimeoutMillis: 30000,
                        // reapIntervalMillis: 1000,
                        // createRetryIntervalMillis: 100,
                        propagateCreateError: false // <- default is true, set to false
                    },
                    migrations: {
                        tableName: 'knex_migrations'
                    }
                }
                

                如果它不适合您,请尝试将propagateError 设置为true 并取消注释

                 "idleTimeoutMillis": 30000,
                 "createTimeoutMillis": 30000,
                 "acquireTimeoutMillis": 30000
                

                【讨论】:

                  猜你喜欢
                  • 2020-09-07
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-04-13
                  • 1970-01-01
                  • 2018-03-30
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多