如何在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
相关产品推荐
相关产品推荐

