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

Node.js调用API查询船只数据时交替返回结果问题求助

Node.js调用MySQL存储过程结果交替异常的解决方案

问题现象

新增条目(通过MySQL或Postman操作)后,按用户过滤检索boats条目时,结果交替出现:第一次正常返回全部数据,第二次无结果,第三次正常,第四次又无结果。

已知信息

  • 直接在MySQL中调用存储过程sp_get_boat_summary始终返回正确数据
  • 等待4-5分钟后API自动恢复正常
  • 重启nodemon服务后API也能正常响应所有请求

现有代码

数据库连接文件(database.js)

const mysql = require('mysql');
//const mysql = require('mysql2');
const util = require ('util');
 
const pool = mysql.createPool({
     connectionLimit: 10,
     host: 'x.xxx.xx.xxx',
     user: 'xxxxx-xxx',
     password: 'xxxxxxxxxxxx',
     database: 'xxxxxxxxxxxx',
     port: 3306,
     queueLimit: 1000, 
});
 
pool.getConnection((err,connection)=> {
     if(err) throw err;
     console.log('Database connected successfully');
     connection.release();
});
        
module.exports = pool;

控制器文件(trxController.js)

const trxModel = require('../models/trxModels');
 
// Async
const getboatsummaryAsync = util.promisify(trxModel.boatsummary);
 
exports.boatsummary = async (req, res) => {
     try {
         const input = req.params.usercode;
         const response_data = await getboatsummaryAsync(input) // Call user model
 
         if (!response_data){
             return res.status(404).json({ error: 'User not found in DB' });
         }
 
         return res.status(200).json(response_data);
     
     } catch (error) {
         console.log('Error in boatSummary: ', error)
         return res.status(500).json({ error: 'Internal server error' });
     } 
};

模型文件(trxModels.js)

const db = require('../config/database.js');
 
const db = require('../config/database.js');
    static async boatsummary(input, callback) {
 
     const sql = 'CALL sp_get_boat_summary(?);'; 
     
     await db.query(sql, [input], function (error, results) { 
         console.log(input);
         if (error)  return callback(error, null);  
 
         const formattedResults = results[0].map((row) => ({ ...row }));
 
         return callback(null,formattedResults);
     });
     
 }

问题根源

  1. 异步逻辑混乱:模型中boatsummary方法标记为async,但内部使用回调式的db.query,await对回调方法无效,导致util.promisify处理后出现回调状态异常。
  2. 重复引入数据库连接:模型文件中重复require数据库连接,可能导致连接实例冲突。
  3. 连接池状态残留:存储过程调用后,连接池中的连接可能残留未重置的状态,被复用时返回空结果;当连接被自动回收重置(等待超时)或服务重启后,状态恢复正常,因此出现交替现象。

修复方案

方案1:修正异步逻辑(基于原mysql库)

修改模型文件

移除重复的db引入,改用util.promisify处理db.query而非整个方法:

const db = require('../config/database.js');
const util = require('util');

// 绑定db上下文,确保query方法能正确使用连接池
const queryAsync = util.promisify(db.query).bind(db);

static async boatsummary(input) {
    const sql = 'CALL sp_get_boat_summary(?);'; 
    const results = await queryAsync(sql, [input]);
    return results[0].map(row => ({ ...row }));
}

修改控制器文件

无需再手动promisify模型方法,直接调用异步方法:

const trxModel = require('../models/trxModels');
 
exports.boatsummary = async (req, res) => {
     try {
         const input = req.params.usercode;
         const response_data = await trxModel.boatsummary(input);
 
         // 空数组也需要判断,避免无结果时误判
         if (!response_data || response_data.length === 0){
             return res.status(404).json({ error: 'User not found in DB' });
         }
 
         return res.status(200).json(response_data);
     
     } catch (error) {
         console.log('Error in boatSummary: ', error)
         return res.status(500).json({ error: 'Internal server error' });
     } 
};

方案2:改用mysql2(推荐,原生支持Promise)

修改数据库连接文件

切换到mysql2的Promise版本,避免util.promisify的潜在问题:

const mysql = require('mysql2/promise');

const pool = mysql.createPool({
     connectionLimit: 10,
     host: 'x.xxx.xx.xxx',
     user: 'xxxxx-xxx',
     password: 'xxxxxxxxxxxx',
     database: 'xxxxxxxxxxxx',
     port: 3306,
     queueLimit: 1000, 
});

// 测试连接(可选)
(async () => {
    try {
        const connection = await pool.getConnection();
        console.log('Database connected successfully');
        connection.release();
    } catch (err) {
        console.error('Database connection failed:', err);
        process.exit(1);
    }
})();
        
module.exports = pool;

修改模型文件

直接使用Promise风格的query方法:

const db = require('../config/database.js');

static async boatsummary(input) {
    const sql = 'CALL sp_get_boat_summary(?);'; 
    // mysql2的query返回[结果集, 字段信息],取第一个元素
    const [results] = await db.query(sql, [input]);
    return results[0].map(row => ({ ...row }));
}

控制器文件同方案1的修改

验证

修复后,新增条目后多次调用API,应能稳定返回正确结果,不再出现交替无结果的情况。

内容的提问来源于stack exchange,提问作者Guillermo Bastian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 03:01:04