Knex.js / SQL:Knex / SQL 连接池

AJ_*_*AJ_ 2 javascript sql-server node.js knex.js

我有一个关于 SQL 连接池的问题。我的团队正在我们的节点应用程序之一中使用 knex.js 库来进行数据库查询。应用程序不时需要切换数据库。因此,我的团队创建了一个初始化函数,该函数返回配置到正确数据库的 knex 对象。然后该对象用于执行所述查询。对我来说,这似乎是多余的,并且可能会导致性能不佳,因为我们每次需要执行查询时都会启动一个 knex 对象,而不是重用单个 knex 对象。如果 knex 已经在您使用哪些数据库时执行了此操作,我可以忽略这一点(如果有人也能阐明这个问题,那就太棒了!)。此外,(这让我想到了上面的问题)连接池属性被重新定义。那么这是否意味着我们每次都会创建新的池,或者 SQL(在本例中为 SQL Sever)会重用您已经定义的连接池?这个问题可能不是 Knex 特定的,就像如果我在 C# 中使用像 knex 这样的库,并以类似的方式调用该库,SQL Server 会知道不要创建更多连接池吗?

示例代码:

/** db.js
 * @param {any} database 
 * @returns db: Knex
 */
module.exports = ( database ) => {
  var knex = require('knex')({
    client: 'mssql',
    connection: {
        database: database,
        server:  '127.0.0.1',
        user: 'your_database_user',
        password: 'your_database_password'
    },
    pool: {
        min: 0,
        max: 10,
        idleTimeoutMillis: 5000,
        softIdleTimeoutMillis: 2000,
        evictionRunIntervalMillis: 500
    }
  });
  return knex; 
}; 


Index.js

var db = require('./db.js'); 
/**
 * @returns users:Array
 */
const getUsers = async() => {
    const users = await db('master')
            .select()
            .from('users_table')
            .orderBy('user_id'); 
    return users; 
}
Run Code Online (Sandbox Code Playgroud)

Gar*_*ryL 7

简短的回答:节点require()语句的“单例”性质阻止了多次出现的重新初始化knex。因此,只要您不丢弃变量引用,最初创建的池就会在进程期间继续使用,而不是重新创建db.

更多讨论...

...我的团队创建了一个初始化函数,该函数返回配置到正确数据库的 knex 对象。然后该对象用于执行所述查询。对我来说,这似乎是多余的,并且可能会导致性能不佳,因为我们每次需要执行查询时都会启动一个 knex 对象,而不是重用单个 knex 对象。如果当你切换数据库时 knex 已经这样做了,我可以忽略它......

    var db = require('./db.js');
Run Code Online (Sandbox Code Playgroud)

Node.jsrequire语句创建一个单例对象。(您可能已经知道)这意味着程序第一次使用该语句调用模块时require,模块及其数据将被初始化,但连续的相同require调用将仅重用相同的模块引用,而不会重新初始化模块。

...连接池属性被重新定义。那么这是否意味着我们每次都会创建新的池,或者 SQL(在本例中为 SQL Sever)会重用您已经定义的连接池?

因此,由于require()-ed 模块没有重新初始化,那么最初创建的池将不会被重新创建。除非您放弃db变量引用(下面将详细讨论)。

这个问题可能不是 Knex 特定的,就像如果我在 C# 中使用像 knex 这样的库,并以类似的方式调用该库,SQL Server 会知道不要创建更多连接池吗?

一般来说,您需要构建或获取连接一些代码,以便在进程的整个生命周期中正确管理连接池。Knex 和大多数其他数据库包装器为我们做这件事。(在幕后,Knex在 v0.18.3 之前使用这个库,并且在 v0.18.3 之后使用这个库。)

在应用程序进程的整个生命周期中正确初始化并使用单独初始化的池代码可以实现此目的。丢弃池并在进程中重新创建它违背了池化的目的。通常池化是作为进程初始化的一部分设置的。

另外,这可能只是您问题中的错误陈述,但您的 Node.js 模块正在创建连接池,而不是 SQL Server。

...应用程序不时需要切换数据库。我的团队创建了一个初始化函数,该函数返回配置到正确数据库的 knex 对象。

从该声明中,我希望看到如下代码:

var db = require('./db.js');
var dbOther = require('./dbOther.js');
Run Code Online (Sandbox Code Playgroud)

...每个都建立不同的数据库连接。如果您使用:

var db = require('./db.js');
// ... do other stuff here in the same module ...
var db = require('./dbOther.js');
Run Code Online (Sandbox Code Playgroud)

...那么您可能会丢弃对第一个数据库的原始引用,在这种情况下,是的,您在切换连接时会丢弃数据库连接和连接池。

或者,您可以执行如下操作:

// initialize the 2 connection pools
const dbFirst = require('./db.js');
const dbOther = require('./dbOther.js');

// set the active connection
var db = dbFirst;
// change the active connection
db = dbOther;
Run Code Online (Sandbox Code Playgroud)