AWS Lambda连接RDS报错:Cannot enqueue Handshake重复入队
解决MySQL连接在Lambda中首次成功后续报错的问题
这个错误Cannot enqueue Handshake after already enqueuing a Handshake的根源很明确:你把connection实例定义在了Lambda handler的外面,属于全局变量。Lambda的执行环境会被复用——第一次调用时连接成功建立,但后续请求复用同一个容器时,这个连接已经处于握手完成或者已经失效的状态,你再调用connection.connect()就会触发这个错误,因为同一个连接实例不能重复发起握手请求。
下面给你两种可行的解决方案,同时修正你代码里的SQL注入风险:
方案一:每次请求创建新连接
在handler内部创建连接,请求处理完成后关闭连接,这样就不会因为容器复用导致连接状态异常:
var mysql = require('mysql'); exports.handler = async (event) => { // 每次请求都创建新的连接实例 const connection = mysql.createConnection({ host: "-", user: "-", password: "-", database: "-" }); try { const data = await new Promise((resolve, reject) => { connection.connect(function(err) { if (err) { reject(err); return; } // 用占位符替代直接拼接变量,避免SQL注入! const sql = `INSERT INTO forms VALUES(?,2,3,4,5,6,7,8,9,10,11);`; connection.query(sql, [Math.random() * 10000], function(err, result) { // 无论成功失败,都要关闭连接释放资源 connection.end(); if (err) { console.log("Error->" + err); reject(err); } else { resolve(result); } }); }); }); return { statusCode: 200, body: JSON.stringify(data) }; } catch (err) { // 出错时也要确保连接关闭 connection.end(); return { statusCode: 500, body: JSON.stringify({ error: err.message }) }; } };
方案二:使用连接池(推荐,性能更优)
连接池会自动管理连接的创建、复用和销毁,既能避免重复创建连接的开销,又能处理连接状态的问题,适合Lambda场景:
var mysql = require('mysql'); // 全局创建连接池(容器复用时可以复用整个池,不用重新初始化) const pool = mysql.createPool({ host: "-", user: "-", password: "-", database: "-", connectionLimit: 10 // 根据你的请求量调整连接数上限 }); exports.handler = async (event) => { try { const data = await new Promise((resolve, reject) => { // 从连接池中获取可用连接 pool.getConnection(function(err, connection) { if (err) { reject(err); return; } // 同样使用占位符防止SQL注入 const sql = `INSERT INTO forms VALUES(?,2,3,4,5,6,7,8,9,10,11);`; connection.query(sql, [Math.random() * 10000], function(err, result) { // 将连接放回池中,供后续请求复用 connection.release(); if (err) { console.log("Error->" + err); reject(err); } else { resolve(result); } }); }); }); return { statusCode: 200, body: JSON.stringify(data) }; } catch (err) { return { statusCode: 500, body: JSON.stringify({ error: err.message }) }; } };
额外注意事项
- SQL注入风险:你的原始代码直接把
Math.random()*10000拼到SQL语句里,这是非常危险的做法,一定要用占位符?配合参数数组传递变量,上面的代码已经帮你修正了这一点。 - 资源释放:无论请求成功还是失败,都要确保连接被关闭(方案一)或者放回池(方案二),避免资源泄漏导致的其他问题。
内容的提问来源于stack exchange,提问作者excitelybored
相关产品推荐
相关产品推荐

