Node.js中如何重置MySQL连接?解决仅能执行6次查询问题
问题诊断与解决方案
核心原因分析
你的服务器执行6次查询后无响应,大概率是两个问题叠加导致:
- HTTP请求未收尾:
app.post("/input")路由里调用addToDatabase后,没给客户端返回任何响应(比如res.send()),导致每个请求一直挂着,占着连接池里的连接。当连接池默认的5-6个连接被耗尽,新请求拿不到连接,服务器就停了响应。 - 错误处理不当+连接泄漏:回调里直接
throw err会触发未捕获异常,可能让连接池里的连接没法正常释放;嵌套的查询如果出错,也会导致连接收不回来,加速耗尽。
分步解决方案
1. 先补全HTTP响应,释放请求连接
不管操作成功还是失败,都要给客户端返回响应,不然请求会一直占着连接:
app.post("/input", (req,res) => { if(req.body.code) { addToDatabase(...., res); // 把res传给处理函数 } else { addToDatabase(...., res); } }); function addToDatabase(...., res, variant = "") { // 改用参数化查询,避免注入和语法错 con.query("SELECT * FROM inventory WHERE id_inventory = ?", [....], function (err,result) { if(err) { console.error(err); return res.status(500).send("查询失败"); // 错误时返回响应 } if(result.length > 0) { con.query("UPDATE .... WHERE id_inventory = ?", [....], function (err2, result2) { if(err2) { console.error(err2); return res.status(500).send("更新失败"); } console.log("UPDATE完成"); res.send("更新成功"); // 成功后返回响应 }); } else { let sql, params; if(variant === "") { sql = "INSERT INTO inventory .... VALUES (?, ?)"; params = [....]; } else { sql = "INSERT INTO inventory .... VALUES (?, ?, ?)"; params = [...., variant]; } con.query(sql, params, function (err, result) { if(err) { console.error(err); return res.status(500).send("插入失败"); } console.log("INSERT完成"); res.send("插入成功"); // 成功后返回响应 }); } }); }
2. 必须用参数化查询,别直接拼SQL
你现在直接把变量拼进SQL里,不仅有SQL注入风险,还可能因为特殊字符导致SQL语法错误,进而引发连接泄漏。用?当占位符,把参数放进数组传给query是标准做法。
3. 优化连接池配置(可选)
如果确实需要更多并发连接,可以调大连接池的最大连接数,但这只是辅助,核心还是要解决连接泄漏:
var con = mysql.createPool({ host: "localhost", database: "....", user: "....", port: ...., password: "....", connectionLimit: 20, // 按需调大连接数 waitForConnections: true, queueLimit: 0 });
4. 改用async/await简化代码(推荐)
回调嵌套容易出错,改用mysql2/promise的异步语法,错误处理更清晰,也能减少连接泄漏概率:
const mysql = require("mysql2/promise"); const pool = mysql.createPool({ host: "localhost", database: "....", user: "....", port: ...., password: "...." }); app.post("/input", async (req,res) => { try { if(req.body.code) { await addToDatabase(...., req.body.code); } else { await addToDatabase(....); } res.send("操作成功"); } catch (err) { console.error(err); res.status(500).send("操作失败"); } }); async function addToDatabase(...., variant = "") { const [rows] = await pool.query("SELECT * FROM inventory WHERE id_inventory = ?", [....]); if(rows.length > 0) { await pool.query("UPDATE .... WHERE id_inventory = ?", [....]); console.log("UPDATE完成"); } else { let sql, params; if(variant === "") { sql = "INSERT INTO inventory .... VALUES (?)"; params = [....]; } else { sql = "INSERT INTO inventory .... VALUES (?, ?)"; params = [...., variant]; } await pool.query(sql, params); console.log("INSERT完成"); } }
5. 排除MySQL端限制
MySQL默认没有单连接查询次数限制,你可以登录本地MySQL执行以下命令验证:
SHOW VARIABLES LIKE 'max_connections'; -- 看最大连接数,默认151左右,肯定够个人项目用 SHOW VARIABLES LIKE 'wait_timeout'; -- 连接超时默认8小时,不会导致这个问题
验证效果
改完代码后测试:
- 每次请求都能收到明确响应,不会挂着
- 服务器能持续处理超过6次查询
- 可以打印连接池状态(比如
pool._allConnections.length),确认连接会被正确回收
内容的提问来源于stack exchange,提问作者Kevin2Holt
相关产品推荐
相关产品推荐

