节点JS Express-Oracle连接池(ORA-24418:无法打开其他会话)

ash*_*ash 4 sql oracle node.js express

我在使用Oracle DB模块时遇到问题:https : //github.com/oracle/node-oracledb/blob/master/doc/api.md

我有一个应用程序,每小时有300到900次匹配(通常来自大约100个用户)。该应用程序在后台有许多$ .post请求,以从数据库中检索信息并显示给用户。

我最近切换到了该模块,因为它是Oracle自己的(我以前使用的是https://github.com/joeferner/node-oracle)。

这是我列出的方式:

/ 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

 }
)
Run Code Online (Sandbox Code Playgroud)

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

  })

}
Run Code Online (Sandbox Code Playgroud)

}

该模块“ acquire_and_query”在我们的应用程序中从中调用,并具有SQL及其传入的参数以执行。

Oracle数据库的“池化连接”最大允许设置为80(并且我们没有超过它们)-通常看起来很高兴。

但是,节点应用程序不断抛出ORA-24418:无法打开其他会话,我不确定如何解决此问题。

谢谢。

ash*_*ash 6

解决-问题:我的编码不好!

我曾无意中设置Socket.IO事件来更新为大家连接多次的观点(而不是查询一次数据库,然后再送上的视图插座...)叹息

我还更加愚蠢地在基于事务的查询中使用for循环(每次运行都会插入多个数据)...一旦将其更改为递归模式-它就畅快地运行了!

此处提供有关循环和递归模式的好文章:http : //www.richardrodger.com/2011/04/21/node-js-how-to-write-a-for-loop-with-callbacks/#.VaQjJJNViko

无论如何-这就是我现在使用的方法(效果很好),使用node-oracledb v0.6(https://github.com/oracle/node-oracledb)和Express 4(http://expressjs.com/

斌/ www

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

});
Run Code Online (Sandbox Code Playgroud)

libs / oracledb.js

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;

}
Run Code Online (Sandbox Code Playgroud)

用法示例

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

}
Run Code Online (Sandbox Code Playgroud)