Node.js+MySQL部署Railway后闲置查询报错:Cannot read properties of undefined
问题解决思路与方案
问题根源
闲置后数据库连接被MySQL服务器主动断开(默认MySQL的wait_timeout为8小时,闲置连接会被自动关闭),而代码未处理数据库查询的错误,同时使用单个长连接而非连接池管理连接,导致连接断开后后续查询失败,results变为undefined,进而访问results.length抛出错误。重启应用会重新建立连接,因此暂时恢复正常。
具体修复步骤
1. 立即补全错误捕获逻辑
在数据库查询的回调中优先检查error参数,避免出错时继续访问results:
db.query('SELECT * FROM donors WHERE email = ?', [email], async (error, results) => { // 先处理数据库查询错误 if (error) { console.error('数据库查询失败:', error); return res.status(500).render('donor/donorlogin', { message: '服务器内部错误,请稍后重试' }); } console.log(results); if (results.length === 0 || !(await bcrypt.compare(password, results[0].password))) { res.status(401).render('donor/donorlogin', { message: 'Email or Password is incorrect' }); } else { const id = results[0].id; const token = jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN }); console.log("The token is: " + token); const cookieOptions = { expires: new Date( Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000 ), httpOnly: true }; res.cookie('jwt', token, cookieOptions); res.status(200).redirect('/donor/dashboard'); } });
2. 改用数据库连接池替代单个连接
单个长连接易因闲置被断开,连接池会自动管理连接的创建、复用与重连。修改数据库配置文件(如db.js):
const mysql = require('mysql2'); // 推荐使用mysql2,原生支持Promise与连接池 const pool = mysql.createPool({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, connectionLimit: 10, // 连接池最大连接数 waitForConnections: true, queueLimit: 0 }); // 导出Promise化的连接池,方便后续使用async/await module.exports = pool.promise();
3. 正确使用async/await写法(可选)
若要改用async/await,确保query方法已Promise化,同时用try/catch捕获全局错误:
// 假设db是Promise化的连接池 try { // mysql2的query返回[查询结果, 字段信息],需取第一个元素 const [results] = await db.query('SELECT * FROM donors WHERE email = ?', [email]); if (results.length === 0 || !(await bcrypt.compare(password, results[0].password))) { return res.status(401).render('donor/donorlogin', { message: 'Email or Password is incorrect' }); } // 登录成功逻辑... const id = results[0].id; const token = jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRES_IN }); const cookieOptions = { expires: new Date( Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000 ), httpOnly: true }; res.cookie('jwt', token, cookieOptions); res.status(200).redirect('/donor/dashboard'); } catch (error) { console.error('数据库操作失败:', error); return res.status(500).render('donor/donorlogin', { message: '服务器内部错误,请稍后重试' }); }
额外建议
- 检查Railway平台MySQL实例的
wait_timeout和interactive_timeout配置,必要时调整闲置超时时间; - 添加全局错误处理中间件,避免未捕获的错误导致应用崩溃。
内容的提问来源于stack exchange,提问作者Tushar Rusia
相关产品推荐
相关产品推荐

