Node.js连接MySQL报PROTOCOL_ENQUEUE_HANDSHAKE_TWICE错误如何解决
报错原因
PROTOCOL_ENQUEUE_HANDSHAKE_TWICE报错的根本原因就是你对同一个数据库连接实例重复调用了connect()方法。通过mysql.createConnection()创建的连接对象,只需要执行一次握手连接,之后可以直接多次调用query()执行SQL语句,不需要重复建立连接。
修复方案
推荐直接使用数据库连接池代替单次创建连接,连接池会自动管理连接的复用、销毁,并发场景下性能和稳定性更高,同时也能避免重复连接的问题。修改后的mysql.js代码如下:
// 导入mysql库 import mysql from "mysql" // 创建数据库连接池 const pool = mysql.createPool({ host: "localhost", user: "root", password: "*******", database: "store_user_info", connectionLimit: 10 // 可根据业务需求调整连接数上限 }) export let run_db = (insert_values, callback) => { // 从连接池获取可用连接 pool.getConnection((err, db_connect) => { if (err) throw err // 校验邮箱/用户名是否存在,直接加WHERE条件查询,不用查全表性能更高 const checkSql = `SELECT * FROM Users WHERE email = ? OR username = ?` // 使用参数化查询,避免SQL注入漏洞 db_connect.query(checkSql, [insert_values.email, insert_values.username], (err, result) => { if (err) { db_connect.release() // 操作完成释放连接回连接池 throw err } if (result.length > 0) { console.log("email/username已被占用") db_connect.release() callback?.({status: 'fail', msg: '邮箱或用户名已被占用'}) return } // 校验通过执行插入 const insertSql = `INSERT INTO Users (email,password,username) VALUES (?, ?, ?)` db_connect.query(insertSql, [insert_values.email, insert_values.password, insert_values.username], (err, result) => { db_connect.release() if (err) throw err console.log("用户注册成功") callback?.({status: 'success', msg: '注册成功'}) }) }) }) }
对应修改express.js中的路由逻辑,增加返回响应给前端,避免前端请求超时:
// 原路由命名和实际功能不符,建议修改为/register app.post('/register', (req, res) =>{ const json_db_value = { "email": req.body.email.toString(), "password": req.body.password.toString(), "username": req.body.username.toString() } run_db(json_db_value, (result) => { res.json(result) }) })
其他优化建议
- 不要明文存储用户密码,推荐使用bcrypt等加密库对密码加盐哈希后再存入数据库,避免数据泄露后用户密码明文外泄
- 原代码中直接拼接SQL字符串的写法存在SQL注入风险,一定要使用参数化查询的写法传递查询参数
内容的提问来源于stack exchange,提问作者mythic lisp
相关产品推荐
相关产品推荐

