我想我会更新这个以防其他人遇到类似的麻烦。 @AlwaysLearning 为我提供了 mssql npm 文档的一部分的链接,该文档解释了连接池以及在需要访问多个数据库时执行此操作。我建议通读它 https://www.npmjs.com/package/mssql#advanced-pool-management.
原来mssql的.connect()函数是全局的。如果调用 .connect() 函数时全局池已经连接,它将解析为已连接的池。这给我带来了麻烦,因为当快速连续发送两个请求时,我的应用程序中会发生以下情况:
- 请求 1 将连接到数据库 A
- 请求2将尝试连接到数据库B
- 由于数据库 A 已在全局池中连接,因此请求 2 获取数据库 A 连接
- 请求2的SQL查询失败,因为它对于数据库A无效
为了解决这个问题,您需要开发一些连接池管理代码。通过这种方式,您可以确保每个必要的数据库连接都有单独的连接池。此外,这是一种加快查询速度的简单方法,因为您不必每次发出请求时都重新连接到数据库。
npm 文档提供了几个示例帮助程序文件,但我发现它们对我来说并不理想,而且我无法编译我的环境中的所有代码。我将代码定制如下:
mssql-connection-pooling.js:
const { ConnectionPool } = require('mssql')
const pools = {}
// create a new connection pool
function CreatePool(config) {
let key = JSON.stringify(config)
if (GetPool(key))
throw new Error('Pool already exists')
pools[key] = (new ConnectionPool(config)).connect()
return pools[key]
}
// get a connection pool from all pools
function GetPool(name) {
if (pools[name])
return pools[name]
else
return null
}
// if pool already exists, return it, otherwise create it
function GetCreateIfNotExistPool(config) {
let key = JSON.stringify(config)
let pool = GetPool(key)
if(pool)
return pool
else
return CreatePool(config)
}
// close a single pool
function ClosePool(config) {
let key = JSON.stringify(config)
if (pools[key]) {
const pool = pools[key];
delete pools[key];
pool.close()
return true
}
return false
}
// close all the pools
function CloseAllPools() {
pools.forEach((pool) => {
pool.close()
})
pools = {}
return true
}
module.exports = {
ClosePool,
CloseAllPools,
CreatePool,
GetPool,
GetCreateIfNotExistPool
}
我创建了 GetCreateIfNotExistPool() 函数,您可以通过该函数提供数据库连接配置对象。该函数检查池中是否存储了给定连接配置的打开连接。如果有,它只是返回连接池。如果没有,它会创建它然后返回它。
使用示例:
const sql = require("mssql");
let mssql = require('./mssql-pool-management.js')
let exampleDBConfigA = {
user: 'test',
password: 'password,
server: 'SqlServerA',
database: 'DatabaseA'
};
let exampleDBConfigB = {
user: 'test',
password: 'password,
server: 'SqlServerB',
database: 'DatabaseB'
};
...
// Request 1
try {
let sqlPool = await mssql.GetCreateIfNotExistPool(exampleDBConfigA)
let request = new sql.Request(sqlPool)
// query code
}
catch(error) {
//error handling
}
...
// Request 2
try {
let sqlPool = await mssql.GetCreateIfNotExistPool(exampleDBConfigB)
let request = new sql.Request(sqlPool)
// query code
}
catch(error) {
//error handling
}
在此示例中,请求 1 和 2 可以同时调用,而不会干扰它们的连接!