mysql after 报错_Node.js中使用mysql时报错Error: Cannot enqueue Query after invoking quit.的解决方法...

Error: Cannot enqueue Query after invoking quit.

at Protocol._validateEnqueue (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/protocol/Protocol.js:215:16)

at Protocol._enqueue (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/protocol/Protocol.js:138:13)

at Connection.query (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/Connection.js:201:25)

at Query. (/Users/jabingp/Github/CodeSharing/dist/backEnd/db/DB.js:86:34)

at Query. (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/Connection.js:525:10)

at Query._callback (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/Connection.js:491:16)

at Query.Sequence.end (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24)

at Query._handleFinalResultPacket (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/protocol/sequences/Query.js:139:8)

at Query.OkPacket (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/protocol/sequences/Query.js:72:10)

at Protocol._parsePacket (/Users/jabingp/Github/CodeSharing/node_modules/mysql/lib/protocol/Protocol.js:291:23)

出错代码如下

updateDatas(datas:Array){

this.connect();

console.log("要修改的数据:")

console.log(datas);

for(let data of datas){

this.connection.query(`update test set name = "${data.name}" where id = ${data.id}`,(error, results) =>{

if (error) throw error;

console.log(results);

this.connection.query('SELECT * from test', function (error, results, fields) {

if (error) throw error;

console.log("查询结果是");

console.log(results);

});

});

}

this.end();

}

这段代码我想完成的事情是每次更新后都查询所有的值,输出一下每个值的当前状态,然后执行完所有查询就把数据库关闭。

解决方案

从错误中可以看出来大概是数据库以及关闭了,但代码却执行了数据库操作,我们把最下面的this.end()去掉,代码就成功执行了,或者在代码运行的其他阶段执行this.end(),避免数据库连接关闭的情况下执行数据库查询操作。

执行结果

更改数据

要修改的数据:

[ { name: 'change Hello World again', id: 4 },

{ name: 'change Hellow JabinGP again', id: 5 } ]

connected as id 285992

OkPacket {

fieldCount: 0,

affectedRows: 1,

insertId: 0,

serverStatus: 2,

warningCount: 0,

message: '(Rows matched: 1 Changed: 0 Warnings: 0',

protocol41: true,

changedRows: 0 }

OkPacket {

fieldCount: 0,

affectedRows: 1,

insertId: 0,

serverStatus: 2,

warningCount: 0,

message: '(Rows matched: 1 Changed: 0 Warnings: 0',

protocol41: true,

changedRows: 0 }

查询结果是

[ RowDataPacket { id: 4, name: 'change Hello World again' },

RowDataPacket { id: 5, name: 'change Hellow JabinGP again' } ]

查询结果是

[ RowDataPacket { id: 4, name: 'change Hello World again' },

RowDataPacket { id: 5, name: 'change Hellow JabinGP again' } ]

结果并不是预想的输出一个插入结果后输出一个查询结果,而是两个插入结果先输出后输出两个查询结果,为什么?下面进行个人的推测分析。

原因分析

错误分析

我在前面的文章https://www.jianshu.com/p/59fda67a868e

提到过,connection关闭时并不会直接关闭,而是会将任务队列中的任务都执行完才关闭,而回调是任务执行成功或者失败后调用的,关闭连接时的确会检查任务队列,但是回调函数不在任务队列中,也就是说回调函数里面的:

this.connection.query('SELECT * from test', function (error, results, fields) {

if (error) throw error;

console.log("查询结果是");

console.log(results);

});

这个部分不会被识别为任务队列,所以系统并不会知道这个任务是要再关闭数据库之前执行的,系统仅仅只是确保了循环中的"insert xxx" 会在被关闭连接前执行,但不保证回调中"select * xxx"会在关闭连接前执行,于是在执行这个语句之前数据库连接就关闭了,导致报错。

结果为何不理想

由于for循环执行极快(对比使用网络请求数据库),两个插入操作几乎是同时进入任务队列然后先后执行,执行两个插入操作后此时任务队列为空,不执行任何数据库操作,等待插入操作成功后,输出完两个的结果,代码才执行到查询操作,查询操作才进入任务队列,随后才回调输出查询结果,所以是两个插入先依次输出,两个查询后依次输出。

验证分析

因为node中的mysql是异步的,但是有任务队列机制,我们将查询部分的代码拉出回调,改为和插入并列,这样由于队列机制,执行上也是有先后顺序的,所以能达到我想要的效果:

updateDatas(datas:Array){

this.connect();

console.log("要修改的数据:")

console.log(datas);

for(let data of datas){

this.connection.query(`update test set name = "${data.name}" where id = ${data.id}`,(error, results) =>{

if (error) throw error;

console.log(results);

});

this.connection.query('SELECT * from test', (error, results, fields)=> {

if (error) throw error;

console.log("查询结果是");

console.log(results);

});

}

this.end();

}

执行结果:

更改数据

要修改的数据:

[ { name: 'change Hello World again', id: 4 },

{ name: 'change Hellow JabinGP again', id: 5 } ]

connected as id 285986

OkPacket {

fieldCount: 0,

affectedRows: 1,

insertId: 0,

serverStatus: 2,

warningCount: 0,

message: '(Rows matched: 1 Changed: 0 Warnings: 0',

protocol41: true,

changedRows: 0 }

查询结果是

[ RowDataPacket { id: 4, name: 'change Hello World again' },

RowDataPacket { id: 5, name: 'change Hellow JabinGP again' } ]

OkPacket {

fieldCount: 0,

affectedRows: 1,

insertId: 0,

serverStatus: 2,

warningCount: 0,

message: '(Rows matched: 1 Changed: 0 Warnings: 0',

protocol41: true,

changedRows: 0 }

查询结果是

[ RowDataPacket { id: 4, name: 'change Hello World again' },

RowDataPacket { id: 5, name: 'change Hellow JabinGP again' } ]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误通常表示在MySQL连接上发生了严重的错误,导致连接不再可用。在这种情况下,你需要关闭现有的MySQL连接,然后重新创建一个新的连接。 以下是一个示例代码,演示如何关闭现有连接并创建新连接: ``` const mysql = require('mysql'); let connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'database_name' }); connection.connect((error) => { if (error) { console.error('Error connecting to MySQL database: ' + error.stack); return; } console.log('Connected to MySQL database with ID ' + connection.threadId); // Perform some MySQL queries here... // When you're done, close the connection connection.end((error) => { if (error) { console.error('Error closing MySQL connection: ' + error.stack); return; } console.log('MySQL connection closed'); // Create a new connection connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'database_name' }); connection.connect((error) => { if (error) { console.error('Error connecting to MySQL database: ' + error.stack); return; } console.log('Connected to MySQL database with ID ' + connection.threadId); // Perform some more MySQL queries here... }); }); }); ``` 请注意,以上代码的“localhost”、“root”、“password”和“database_name”应替换为你的MySQL数据库的实际信息。此外,你应该在每个查询之后关闭连接,并在需要重新创建新连接,以避免出现此错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值