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

如何在Express.js中正确使用@mysql/xdevapi?求模板代码

在Express.js中正确使用@mysql/xdevapi开发REST API

错误根源

这个错误的核心问题是你全局创建了单个数据库session,长时间处于空闲状态后,被MySQL的空闲连接超时机制强制断开,后续请求复用这个已失效的session就会触发报错。

正确使用方案

推荐两种适配Express多请求场景的实现方式,优先选择连接池管理方案:

方案一:使用Client管理连接池(高并发场景推荐)

通过mysqlx.getClient()创建客户端实例,它会自动维护连接池,处理连接的复用、重建,无需手动处理重连逻辑,完美适配Web应用的并发请求。

const express = require('express');
const mysqlx = require('@mysql/xdevapi');

const app = express();
app.use(express.json()); // 解析JSON请求体

// 数据库配置
const dbConfig = {
    host: 'mysql',
    port: 33060,
    user: 'root',
    password: 'password',
    schema: 'DB_name',
    // 可选:自定义连接池参数
    pooling: {
        maxSize: 10, // 连接池最大连接数
        queueTimeout: 30000 // 连接等待超时时间(毫秒)
    }
};

// 全局维护Client实例
let dbClient;

// 初始化数据库Client
async function initDbClient() {
    try {
        dbClient = await mysqlx.getClient(dbConfig);
        console.log('MySQL Client 初始化成功');
    } catch (err) {
        console.error('MySQL Client 初始化失败:', err);
        process.exit(1); // 初始化失败直接退出进程
    }
}

// 示例接口:获取数据
async function getData(req, res) {
    let session;
    try {
        // 从连接池获取可用session
        session = await dbClient.getSession();
        const { id } = req.body;
        
        // 必须用参数化查询防止SQL注入,禁止直接拼接SQL!
        const result = await session.sql('SELECT * FROM data_table WHERE id = ?')
            .bind(id) // 绑定查询参数
            .execute();
        
        const data = result.fetchAll();
        res.json({ success: true, data });
    } catch (error) {
        console.error('获取数据失败:', error);
        res.json({ success: false, message: '获取数据失败', detail: error.message });
    } finally {
        // 将session释放回连接池
        if (session) {
            await session.close();
        }
    }
}

app.post('/getData', getData);

// 启动服务器前先初始化数据库Client
initDbClient().then(() => {
    const server = app.listen(3000, '0.0.0.0', () => {
        console.log(`Express服务器运行在 http://${server.address().address}:${server.address().port}`);
    });
});

方案二:每次请求创建新Session(低并发场景适用)

如果应用并发量较低,可以每次请求时创建新session,用完即关闭,从根源避免空闲连接超时问题。

const express = require('express');
const mysqlx = require('@mysql/xdevapi');

const app = express();
app.use(express.json());

const dbConfig = {
    host: 'mysql',
    port: 33060,
    user: 'root',
    password: 'password',
    schema: 'DB_name'
};

async function getData(req, res) {
    let session;
    try {
        // 每次请求创建新的数据库session
        session = await mysqlx.getSession(dbConfig);
        const { id } = req.body;
        
        // 参数化查询防注入
        const result = await session.sql('SELECT * FROM data_table WHERE id = ?')
            .bind(id)
            .execute();
        
        const data = result.fetchAll();
        res.json({ success: true, data });
    } catch (error) {
        console.error('获取数据失败:', error);
        res.json({ success: false, message: '获取数据失败', detail: error.message });
    } finally {
        // 关闭当前session
        if (session) {
            await session.close();
        }
    }
}

app.post('/getData', getData);

app.listen(3000, '0.0.0.0', () => {
    console.log('Express服务器运行在 http://0.0.0.0:3000');
});

关键注意事项

  • 杜绝SQL注入:绝对禁止直接用${id}这类方式拼接SQL语句,必须使用.bind()绑定参数。
  • 连接资源回收:无论哪种方案,都要在finally块中关闭/session,避免连接泄漏导致资源耗尽。
  • 错误日志明细:捕获错误时打印具体信息,不要只返回模糊提示,方便排查问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:55:30