Node.js MySQL偶发ECONNREFUSED错误:特定脚本无法连接数据库求助
我查了不少类似问题,但现有方案都解决不了我的问题。情况是这样的:
- 命令行执行
mysql -hlocalhost -P 3306 -p***能正常连库 - 另一个用完全相同
dbconnection.js的脚本也能正常连接 - 唯独这个特定脚本(Notifications.js)报错:
Error: connect ECONNREFUSED 127.0.0.1:3306
先贴一下相关代码:
dbconnection.js
var mysql = require('mysql'); var connection = mysql.createPool ({ host: '127.0.0.1', user: 'root', password: ****, database: 'test_db', dateStrings: true, port: 3306 }); module.exports = connection;
这个配置在另一个程序里完全正常,到Notifications.js就不行了,相关代码如下:
Notifications.js
var db = require('../dbconnection'); var express = require('express'); var router = express.Router(); router.post('/', function(req,res,next) { handleNotification(req.body.value[0].resource); res.status(202).end(); }); async function handleNotification(resource) { db.query('SELECT of.name, po.PurchaseOrderID FROM order_files AS of \ INNER JOIN purchase_orders AS po ON po.PurchaseOrderID = of.purchaseOrderID \ INNER JOIN quotes ON po.PurchaseOrderID = quotes.PurchaseOrderID \ WHERE quotes.QuoteID=10000', function(err, rows) { if (err) console.log(err); else console.log(rows); }); }
另外,我在bash里用命令行登录MySQL后,执行这段查询是能拿到结果的,而且这个查询在其他脚本里也跑没问题。就纳闷了,为啥偏偏这个脚本连不上?
排查思路与解决方案
既然相同配置在其他环境能跑,问题肯定出在这个脚本的运行环境或代码细节里,给你几个针对性的排查方向:
验证模块加载路径是否正确
你用require('../dbconnection')加载配置,有没有可能脚本的运行目录和正常脚本不一样?比如启动服务时的工作目录不是项目根目录,导致../指向了错误的位置。
可以在Notifications.js里加一行代码确认:console.log(require.resolve('../dbconnection'));看看输出的路径是不是你预期的那个dbconnection.js文件位置。
检查异步代码的执行时机
你的handleNotification是async函数,但内部用的是db.query的回调形式,而且路由处理函数里调用它后立刻返回了响应。有没有可能请求结束后进程提前终止,导致数据库连接还没建立就报错?
可以改成async/await形式确保等待查询完成:async function handleNotification(resource) { try { const rows = await db.query('SELECT of.name, po.PurchaseOrderID FROM order_files AS of INNER JOIN purchase_orders AS po ON po.PurchaseOrderID = of.purchaseOrderID INNER JOIN quotes ON po.PurchaseOrderID = quotes.PurchaseOrderID WHERE quotes.QuoteID=10000'); console.log(rows); } catch (err) { console.log(err); } } // 路由里也改成await调用 router.post('/', async function(req,res,next) { await handleNotification(req.body.value[0].resource); res.status(202).end(); });确认依赖版本与环境一致性
有没有可能这个脚本所在项目的mysql模块版本和正常项目不一致?比如各自有独立的node_modules目录。可以在两个项目里分别执行:npm list mysql对比版本号,某些旧版本的mysql模块在连接池处理上可能存在兼容性问题。
检查连接池配置是否被意外修改
虽然你导出的是固定配置,但有没有可能脚本运行环境中有其他代码篡改了连接池参数?可以在handleNotification里打印配置确认:console.log(db.config);看看输出的host、port是否还是127.0.0.1和3306。
验证端口监听状态
虽然命令行能连,但还是可以确认下MySQL是否真的监听了127.0.0.1:3306:netstat -an | grep 3306确保输出里有
127.0.0.1:3306的监听记录。
先从这几个方向排查,应该能定位到问题所在。
内容的提问来源于stack exchange,提问作者Colin Harrison

