Node.js开发REST API时mariadb连接请求结束后未断开该如何解决
问题原因与解决方案
你当前的代码存在两个核心错误导致数据库连接无法正常释放:
- 连接池初始化位置错误:你将
mariadb.createPool放在了HTTP请求的回调函数内,每收到一个请求就会创建一个全新的独立连接池,即使你关闭了池内的单个连接,连接池实例本身会一直持有资源,不会自动销毁。 - 连接释放方法错误:从连接池获取的连接,用完后应该调用
release()方法归还到连接池,而非end(),end()方法是用来销毁整个连接池实例的,不适用于单个池内连接的释放。
与PHP运行模式的差异说明
PHP为单请求生命周期模型,每个请求对应独立的进程/线程,请求结束后整个进程的所有资源会被系统自动回收,因此不需要手动管理连接。而Node.js是常驻单进程模型,所有创建的资源(连接池、连接实例)都会一直保留在进程内存中,需要主动管理生命周期。
修复方案
推荐方案:全局初始化连接池(性能最优)
连接池的设计目的就是复用连接,全局仅初始化一次即可,无需每次请求创建:
var http = require('http'); var url = require('url'); var mariadb = require('mariadb'); // 全局初始化一次连接池 const dbPool = mariadb.createPool({ host: "localhost", user: "root", password: "", database: "database", connectionLimit: 5 // 可根据业务需求调整连接数上限 }); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'application/json'}); // 从连接池获取连接 dbPool.getConnection() .then(db => { return db.query("select * from array_languages") .then(data => { db.release(); // 查询完成后归还连接到连接池 res.end(JSON.stringify(data)); }) .catch(err => { db.release(); // 查询报错也要释放连接,避免连接泄漏 res.end(JSON.stringify({error: err.message})); }) }) .catch(err => { res.end(JSON.stringify({error: '获取数据库连接失败:' + err.message})); }) }).listen(8080,"localhost");
备选方案:每次请求创建独立连接(性能较低)
如果你不需要连接池,要实现类似PHP那种每次请求用完就彻底关闭连接的效果,可以直接创建单连接而非连接池:
var http = require('http'); var mariadb = require('mariadb'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'application/json'}); // 每次请求新建独立连接 mariadb.createConnection({ host: "localhost", user: "root", password: "", database: "database" }) .then(db => { return db.query("select * from array_languages") .then(data => { db.end(); // 查询完成后直接关闭单连接 res.end(JSON.stringify(data)); }) .catch(err => { db.end(); // 查询报错也要关闭连接 res.end(JSON.stringify({error: err.message})); }) }) .catch(err => { res.end(JSON.stringify({error: '数据库连接失败:' + err.message})); }) }).listen(8080,"localhost");
内容的提问来源于stack exchange,提问作者user15260712
相关产品推荐
相关产品推荐

