Sql Node JS Express-Oracle连接池(ORA-24418:无法打开更多会话)
我在Oracle DB模块中遇到问题: 我有一个每小时有300到900次点击的应用程序(通常是大约100个用户)。应用程序在后台有许多$.post请求,用于从数据库检索信息并显示给用户 我最近切换到这个模块,因为它是Oracle自己的(我以前使用过) 以下是我的陈述: /bin/wwwSql Node JS Express-Oracle连接池(ORA-24418:无法打开更多会话),sql,node.js,oracle,express,Sql,Node.js,Oracle,Express,我在Oracle DB模块中遇到问题: 我有一个每小时有300到900次点击的应用程序(通常是大约100个用户)。应用程序在后台有许多$.post请求,用于从数据库检索信息并显示给用户 我最近切换到这个模块,因为它是Oracle自己的(我以前使用过) 以下是我的陈述: /bin/www oracledb.createPool( { user : 'USER' password : 'PASS', connectString :
oracledb.createPool(
{
user : 'USER'
password : 'PASS',
connectString : 'DB:1521/SID:POOLED',
connectionClass : 'ARBITRARY_NAME',
poolMin : 1,
poolMax : 50,
poolTimeout : 300
},
function(err, pool)
{
if (err) {
console.log(err);
}
require('../libs/db')(pool); // Export pool to separate file
}
)
/**
* Database
*/
// AS PER DOCUMENTATION: https://github.com/oracle/node-oracledb/blob/master/examples/dbconfig.js
var dbconfig = require("../libs/dbconfig.js");
oracledb.connectionClass = dbconfig.connectionClass,
oracledb.createPool({
user: dbconfig.user,
password: dbconfig.password,
connectString: dbconfig.connectString,
poolMax: 44,
poolMin: 2,
poolIncrement: 5,
poolTimeout: 4
}, function(err, pool) {
if (err) {
console.log("ERROR: ", new Date(), ": createPool() callback: " + err.message);
return;
}
require('../libs/oracledb.js')(pool);
});
/libs/db.js
module.exports = function(pool) {
// Require oracle module for formatting
var oracledb = require('oracledb');
// Export acquire and query function
module.exports.acquire_and_query = function(sql, params, callback){
// ACQUIRE connection from pool
pool.getConnection(function(err, connection){
// NUMBER OF CONNCETIONS OPEN
console.log("ORACLE: CONNX OPEN: " + pool.connectionsOpen);
// NUMBER OF CONNEXTIONS IN USE
console.log("ORACLE: CONNX IN USE: " + pool.connectionsInUse);
if (err) {
console.log(err.message);
return;
}
// Use connection to QUERY db and return JSON object
connection.execute(sql, params, {maxRows: 1000, isAutoCommit: true, outFormat: oracledb.OBJECT}, function(err, result){
// Error Handling
if (err) {
console.log(err.message); // Log the error
return false; // Return false for our error handling
}
// Release the connection back to the pool
connection.release(function(err) {
if (err) {
console.log(err.message);
return;
}
})
// Return callback with rowset first, out bind paramaters second
return callback(result.rows, result.outBinds, result.rowsAffected);
})
})
}
module.exports = function(pool) {
////////////////////////////
// INSTANTIATE THE DRIVER //
////////////////////////////
var oracledb = require("oracledb");
//////////////////////
// GET A CONNECTION //
//////////////////////
var doConnect = function(callback) {
console.log("INFO: Module getConnection() called - attempting to retrieve a connection using the node-oracledb driver");
pool.getConnection(function(err, connection) {
// UNABLE TO GET CONNECTION - CALLBACK WITH ERROR
if (err) {
console.log("ERROR: Cannot get a connection: ", err);
return callback(err);
}
// If pool is defined - show connectionsOpen and connectionsInUse
if (typeof pool !== "undefined") {
console.log("INFO: Connections open: " + pool.connectionsOpen);
console.log("INFO: Connections in use: " + pool.connectionsInUse);
}
// Else everything looks good
// Obtain the Oracle Session ID, then return the connection
doExecute(connection, "SELECT SYS_CONTEXT('userenv', 'sid') AS session_id FROM DUAL", {}, function(err, result) {
// Something went wrong, releae the connection and return the error
if (err) {
console.log("ERROR: Unable to determine Oracle SESSION ID for this transaction: ", err);
releaseConnection(connection);
return callback(err);
}
// Log the connection ID (we do this to ensure the conncetions are being pooled correctly)
console.log("INFO: Connection retrieved from the database, SESSION ID: ", result.rows[0]['SESSION_ID']);
// Return the connection for use in model
return callback(err, connection);
});
});
}
/////////////
// EXECUTE //
/////////////
var doExecute = function(connection, sql, params, callback) {
connection.execute(sql, params, { autoCommit: false, outFormat: oracledb.OBJECT, maxRows:1000 }, function(err, result) {
// Something went wrong - handle the data and release the connection
if (err) {
console.log("ERROR: Unable to execute the SQL: ", err);
//releaseConnection(connection);
return callback(err);
}
// Return the result to the request initiator
// console.log("INFO: Result from Database: ", result)
return callback(err, result);
});
}
////////////
// COMMIT //
////////////
var doCommit = function(connection, callback) {
connection.commit(function(err) {
if (err) {
console.log("ERROR: Unable to COMMIT transaction: ", err);
}
return callback(err, connection);
});
}
//////////////
// ROLLBACK //
//////////////
var doRollback = function(connection, callback) {
connection.rollback(function(err) {
if (err) {
console.log("ERROR: Unable to ROLLBACK transaction: ", err);
}
return callback(err, connection);
});
}
//////////////////////////
// RELEASE A CONNECTION //
//////////////////////////
var doRelease = function(connection) {
connection.release(function(err) {
if (err) {
console.log("ERROR: Unable to RELEASE the connection: ", err);
}
return;
});
}
//////////////////////////////
// EXPORT THE FUNCTIONALITY //
//////////////////////////////
module.exports.doConnect = doConnect;
module.exports.doExecute = doExecute;
module.exports.doCommit = doCommit;
module.exports.doRollback = doRollback;
module.exports.doRelease = doRelease;
}
}
这个模块“acquire_and_query”在我们的应用程序中是从中调用的,它具有要执行的SQL及其参数
OracleDB将池连接的最大允许数设置为80(我们没有超过),并且通常看起来非常满意
然而,节点应用程序不断抛出ORA-24418:无法打开更多会话,我不确定如何解决这个问题
谢谢。当到达OCISessionPoolCreate中提供的sessMax参数时,会引发此错误消息 因此,我的第一步是验证数据库会话是否正确关闭 出现此错误消息时,请执行以下三个操作: 1.-(使用sqlplus)显示参数sess 2.-(使用sqlplus) 从v$session中选择用户名、计算机、程序、计数(*) 按用户名、计算机、程序分组 4号命令 3.-在alert.log中验证此事件期间是否存在任何其他ORA-消息
您是否执行了这些步骤?(分享您的结果)已解决-问题:我糟糕的编码 我无意中设置了一个Socket.IO事件来多次更新连接的每个人的视图(而不是查询数据库一次,然后通过套接字发送视图…) 在基于事务的查询中,我甚至更愚蠢地使用for循环(每次运行时插入多个数据)。。。一旦我将其更改为递归模式,它就可以顺利运行了 关于循环和递归模式的好文章: 无论如何,这是我现在使用的(而且效果相当好) 使用节点oracledbv0.6()和express4() bin/www
oracledb.createPool(
{
user : 'USER'
password : 'PASS',
connectString : 'DB:1521/SID:POOLED',
connectionClass : 'ARBITRARY_NAME',
poolMin : 1,
poolMax : 50,
poolTimeout : 300
},
function(err, pool)
{
if (err) {
console.log(err);
}
require('../libs/db')(pool); // Export pool to separate file
}
)
/**
* Database
*/
// AS PER DOCUMENTATION: https://github.com/oracle/node-oracledb/blob/master/examples/dbconfig.js
var dbconfig = require("../libs/dbconfig.js");
oracledb.connectionClass = dbconfig.connectionClass,
oracledb.createPool({
user: dbconfig.user,
password: dbconfig.password,
connectString: dbconfig.connectString,
poolMax: 44,
poolMin: 2,
poolIncrement: 5,
poolTimeout: 4
}, function(err, pool) {
if (err) {
console.log("ERROR: ", new Date(), ": createPool() callback: " + err.message);
return;
}
require('../libs/oracledb.js')(pool);
});
libs/oracledb.js
module.exports = function(pool) {
// Require oracle module for formatting
var oracledb = require('oracledb');
// Export acquire and query function
module.exports.acquire_and_query = function(sql, params, callback){
// ACQUIRE connection from pool
pool.getConnection(function(err, connection){
// NUMBER OF CONNCETIONS OPEN
console.log("ORACLE: CONNX OPEN: " + pool.connectionsOpen);
// NUMBER OF CONNEXTIONS IN USE
console.log("ORACLE: CONNX IN USE: " + pool.connectionsInUse);
if (err) {
console.log(err.message);
return;
}
// Use connection to QUERY db and return JSON object
connection.execute(sql, params, {maxRows: 1000, isAutoCommit: true, outFormat: oracledb.OBJECT}, function(err, result){
// Error Handling
if (err) {
console.log(err.message); // Log the error
return false; // Return false for our error handling
}
// Release the connection back to the pool
connection.release(function(err) {
if (err) {
console.log(err.message);
return;
}
})
// Return callback with rowset first, out bind paramaters second
return callback(result.rows, result.outBinds, result.rowsAffected);
})
})
}
module.exports = function(pool) {
////////////////////////////
// INSTANTIATE THE DRIVER //
////////////////////////////
var oracledb = require("oracledb");
//////////////////////
// GET A CONNECTION //
//////////////////////
var doConnect = function(callback) {
console.log("INFO: Module getConnection() called - attempting to retrieve a connection using the node-oracledb driver");
pool.getConnection(function(err, connection) {
// UNABLE TO GET CONNECTION - CALLBACK WITH ERROR
if (err) {
console.log("ERROR: Cannot get a connection: ", err);
return callback(err);
}
// If pool is defined - show connectionsOpen and connectionsInUse
if (typeof pool !== "undefined") {
console.log("INFO: Connections open: " + pool.connectionsOpen);
console.log("INFO: Connections in use: " + pool.connectionsInUse);
}
// Else everything looks good
// Obtain the Oracle Session ID, then return the connection
doExecute(connection, "SELECT SYS_CONTEXT('userenv', 'sid') AS session_id FROM DUAL", {}, function(err, result) {
// Something went wrong, releae the connection and return the error
if (err) {
console.log("ERROR: Unable to determine Oracle SESSION ID for this transaction: ", err);
releaseConnection(connection);
return callback(err);
}
// Log the connection ID (we do this to ensure the conncetions are being pooled correctly)
console.log("INFO: Connection retrieved from the database, SESSION ID: ", result.rows[0]['SESSION_ID']);
// Return the connection for use in model
return callback(err, connection);
});
});
}
/////////////
// EXECUTE //
/////////////
var doExecute = function(connection, sql, params, callback) {
connection.execute(sql, params, { autoCommit: false, outFormat: oracledb.OBJECT, maxRows:1000 }, function(err, result) {
// Something went wrong - handle the data and release the connection
if (err) {
console.log("ERROR: Unable to execute the SQL: ", err);
//releaseConnection(connection);
return callback(err);
}
// Return the result to the request initiator
// console.log("INFO: Result from Database: ", result)
return callback(err, result);
});
}
////////////
// COMMIT //
////////////
var doCommit = function(connection, callback) {
connection.commit(function(err) {
if (err) {
console.log("ERROR: Unable to COMMIT transaction: ", err);
}
return callback(err, connection);
});
}
//////////////
// ROLLBACK //
//////////////
var doRollback = function(connection, callback) {
connection.rollback(function(err) {
if (err) {
console.log("ERROR: Unable to ROLLBACK transaction: ", err);
}
return callback(err, connection);
});
}
//////////////////////////
// RELEASE A CONNECTION //
//////////////////////////
var doRelease = function(connection) {
connection.release(function(err) {
if (err) {
console.log("ERROR: Unable to RELEASE the connection: ", err);
}
return;
});
}
//////////////////////////////
// EXPORT THE FUNCTIONALITY //
//////////////////////////////
module.exports.doConnect = doConnect;
module.exports.doExecute = doExecute;
module.exports.doCommit = doCommit;
module.exports.doRollback = doRollback;
module.exports.doRelease = doRelease;
}
示例用法
//////////////////////////////
// REQUIRE RELEVANT MODULES //
//////////////////////////////
var db = require("../libs/oracledb.js");
var oracledb = require('oracledb');
var sql = "";
///////////////////////////
// RETRIEVE CURRENT DATE //
///////////////////////////
module.exports.getCurDate = function(callback) {
sql = "SELECT CURRENT_DATE FROM DUAL";
db.doConnect(function(err, connection){
console.log("INFO: Database - Retrieving CURRENT_DATE FROM DUAL");
if (err) {
console.log("ERROR: Unable to get a connection ");
return callback(err);
} else {
db.doExecute(
connection, sql
, {} // PASS BIND PARAMS IN HERE - SEE ORACLEDB DOCS
, function(err, result) {
if (err) {
db.doRelease(connection); // RELEASE CONNECTION
return callback(err); // ERROR
} else {
db.doRelease(connection); // RELEASE CONNECTION
return callback(err, result.rows); // ALL IS GOOD
}
}
);
}
});
}
也许你有空闲的连接?只是一个建议:您正在
pool.connections的回调中记录pool.getConnection
。试着把它放在前面,这样在尝试连接之前你会看到连接的数量。谢谢你,罗德里戈-我会试试的。不过出于兴趣,我已经按照Oracle文档中的定义(在示例webapp.js中)对此进行了设置-您认为它可能没有正确地释放连接吗?如果此数据库仅由您的node.js应用程序使用,则可能是这样。或者其他应用程序也使用相同的数据库,比如监控应用程序(比如Lab128)?谢谢Daniel<代码>处理107 250会话57 268 400 400
警报日志中没有任何有趣的内容。