Node.js oracledb getConnection('hr')方法运行数小时后挂起问题
问题排查与解决方案
1. 修复全局连接变量导致的连接泄漏
你的端点代码中oracleConnApps未声明为局部变量,属于全局变量。并发请求时,多个请求会覆盖这个变量,导致部分连接无法被正确关闭,最终耗尽连接池,后续请求调用getConnection会无限等待(无超时设置),不会触发catch。
修改代码,将连接变量声明为局部变量,并在finally中添加关闭错误的捕获:
app.get('/dbstatus', async (req, res) => { let oracleConnApps; // 声明为局部变量,避免并发干扰 try { oracleConnApps = await oracledb.getConnection('hr'); console.log("DB Connected") // do stuff res.status(200).send({ status: true, data: "OK" }); } catch (err) { console.log("CATCH EXECUTE", err.message); res.status(400).send({ status: false, data: err.message }); } finally { console.log("FINALLY EXECUTE"); if (oracleConnApps) { try { await oracleConnApps.close(); // 捕获关闭连接时的错误 } catch (closeErr) { console.error("Failed to close connection:", closeErr); } } } })
2. 添加getConnection超时设置
oracledb默认调用getConnection时无超时限制,当连接池耗尽后会一直挂起请求。添加超时参数,超过时间会抛出错误进入catch:
// 5秒超时,根据实际情况调整 oracleConnApps = await oracledb.getConnection({ poolAlias: "hr", timeout: 5000 });
3. 配置连接池的连接有效性验证
避免连接池持有已失效的数据库连接(比如被Oracle主动断开的空闲连接),在创建连接池时添加验证配置:
const initialize = async () => { const pool = await oracledb.createPool({ user: 'username', password: 'password', connectString: 'x.x.x.x:1521/sampledev', poolMin: 5, poolMax: 10, poolIncrement: 1, poolAlias: "hr", poolPingInterval: 30, // 每30秒自动ping空闲连接,移除失效连接 connectionValidationCallback: async (conn) => { try { await conn.ping(); return true; } catch (err) { return false; } } }); console.log("Connected to the oracle db pool"); }
也可以在获取连接后手动ping验证:
oracleConnApps = await oracledb.getConnection({ poolAlias: "hr", timeout: 5000 }); await oracleConnApps.ping(); // 验证连接可用再执行后续操作
4. 检查Oracle数据库连接超时配置
确认Oracle服务器的SQLNET.EXPIRE_TIME参数设置,避免数据库频繁断开空闲连接。如果必须设置,确保连接池的ping机制能及时检测并移除失效连接。
5. 排查PM2与进程资源问题
- 使用
pm2 monit监控进程内存使用情况,若内存持续增长,可能存在连接泄漏或其他内存问题 - 确保PM2的日志配置完整,查看是否有未捕获的异常日志
- 尝试更新oracledb到最新稳定版本(如6.5.0),排查是否存在版本特定的连接池bug
内容的提问来源于stack exchange,提问作者HashCode
相关产品推荐
相关产品推荐

