You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 05:03:36