【问题标题】:Knex.js / SQL : Knex / SQL Connection PoolsKnex.js / SQL:Knex / SQL 连接池
【发布时间】:2018-09-10 08:03:55
【问题描述】:

我有一个关于 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; 
}

【问题讨论】:

  • .withSchema([schemaName]) 有什么问题?
  • 如前所述,只导出一个池,查询时使用withSchema。您不需要为每个数据库使用单独的池。
  • 如果您在单个数据库实例中使用多个模式,那么 .withSchema 是一个好主意。但它不适用于访问多个数据库实例。

标签: javascript sql-server node.js knex.js


【解决方案1】:

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

更多讨论...

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

    var db = require('./db.js');

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

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

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

这个问题可能不是 Knex 特定的,比如我使用了一个类似的库 knex for C#,并以类似的方式调用该库,SQL Server 知道不做更多的连接池吗?

一般来说,您需要构建或获取连接一些代码,以便在整个流程生命周期内正确管理连接池。 Knex 和大多数其他数据库包装器为我们执行此操作。 (在幕后,Knex 在 v0.18.3 之前使用 this library,在开启/之后使用 this one。)

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

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

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

从该语句中,我希望看到如下代码:

var db = require('./db.js');
var dbOther = require('./dbOther.js');

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

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

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

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

// 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;

【讨论】:

  • 所以节点在调用 db.js 时不会重新初始化 knex 对象(返回 required('knex')(database)) 的函数,即使我将参数传递给那个 require陈述,对吗?
  • 正确,不会重新初始化knex对象。
  • FWIW 根据他们最新的文档 (knexjs.org/#Installation-pooling),knex 使用 github.com/vincit/tarn.js 作为池
  • 更新了答案以反映 Knex v0.18.3 中池化库的变化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-21
  • 2017-04-29
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
相关资源
最近更新 更多