MySQL 在 node.js 服务器上的空闲时间后给出“读取 ECONNRESET”错误

Posted

技术标签:

【中文标题】MySQL 在 node.js 服务器上的空闲时间后给出“读取 ECONNRESET”错误【英文标题】:MySQL giving "read ECONNRESET" error after idle time on node.js server 【发布时间】:2014-05-19 00:25:56 【问题描述】:

我正在运行一个通过 node-mysql 模块连接到 MySQL 的 Node 服务器。连接和查询 MySQL 最初工作得很好,没有任何错误,但是,让 Node 服务器空闲几个小时后的第一个查询会导致错误。错误是熟悉的read ECONNRESET,来自node-mysql模块的深处。

堆栈跟踪(注意跟踪的三个条目属于我的应用程序的错误报告代码):

Error
at exports.Error.utils.createClass.init (D:\home\site\wwwroot\errors.js:180:16)
at new newclass (D:\home\site\wwwroot\utils.js:68:14)
at Query._callback (D:\home\site\wwwroot\db.js:281:21)
at Query.Sequence.end (D:\home\site\wwwroot\node_modules\mysql\lib\protocol\sequences\Sequence.js:78:24)
at Protocol.handleNetworkError (D:\home\site\wwwroot\node_modules\mysql\lib\protocol\Protocol.js:271:14)
at PoolConnection.Connection._handleNetworkError (D:\home\site\wwwroot\node_modules\mysql\lib\Connection.js:269:18)
at Socket.EventEmitter.emit (events.js:95:17)
at net.js:441:14
at process._tickCallback (node.js:415:13)

此错误发生在我的云节点服务器和 MySQL 服务器以及两者的本地设置上。

我的问题:

    这个问题似乎是 Node 与我的 MySQL 服务器的连接断开,可能是由于连接生命周期限制?

    当使用连接池时,node-mysql 应该优雅地处理断开连接并将它们从池中删除。在我进行查询之前是否不知道断开连接,从而使错误不可避免?

    考虑到我在其他 *** 帖子中经常看到“读取 ECONNRESET”错误,我是否应该从 MySQL 中寻找其他地方来诊断问题?

更新:经过更多浏览,我认为我的问题与this one 重复。看来他的连接也断开了,但没有人建议如何保持连接处于活动状态或如何解决第一次查询失败之外的错误。

【问题讨论】:

【参考方案1】:

如果在建立单个重用连接时发生这种情况,可以通过建立连接池来避免。

例如,如果你正在做这样的事情......

var db = require('mysql')
  .createConnection(...)
  .connect(function(err));

改为这样做...

var db = require('mysql')
  .createPool(...);

【讨论】:

无论是使用单个连接还是池,我仍然遇到这个问题。正如我接受的答案概述的那样,这是 MySQL 挂起并且 node-mysql 没有意识到它的症状。从那以后这可能已经修复了,因为我已经使用它很多年了。 感谢您的洞察力。我最近遇到同样的错误时发现了这篇文章。切换到使用连接池为我解决了这个问题,所以我发布了这个来帮助处于同样情况的其他人。【参考方案2】:

我在their Github page 上联系了node-mysql 人员并得到了一些确定的答案。

    MySQL 确实会修剪空闲连接。有一个 MySQL 变量“wait_timeout”设置超时前的秒数,默认为 8 小时。我们可以将默认值设置为远大于此。使用show variables like 'wait_timeout'; 查看您的超时设置并使用set wait_timeout=28800; 进行更改。

    根据this issue,node-mysql 在此类断开连接后不会修剪池连接。模块开发人员建议使用心跳来保持连接,例如每隔一段时间调用SELECT 1;。他们还建议使用 node-pool module 及其 idleTimeoutMillis 选项来自动修剪空闲连接。

【讨论】:

您的问题和回答对我很有帮助。你有尝试过节点池模块的经历吗?你可能有具体的例子吗? 添加/etc/my.cnf wait_timeout=28800;这是工作:-)【参考方案3】:

这个问题是否似乎是 Node 与我的 MySQL 服务器的连接断开,可能是由于连接生命周期限制?

是的。服务器已关闭其连接端。

当使用连接池时,node-mysql 应该优雅地处理断开连接并将它们从池中删除。在我进行查询之前是否不知道断开连接,从而使错误不可避免?

正确,但它应该在内部处理错误,而不是将其传回给您。这似乎是 node-mysql 中的一个错误。举报吧。

考虑到我在其他 *** 帖子中经常看到“读取 ECONNRESET”错误,我是否应该从 MySQL 中寻找其他地方来诊断问题?

这要么是 node-MySQL 连接池实现中的错误,要么您没有正确配置它以检测故障。

【讨论】:

谢谢!我已经在node-mysql's Github page 上报告了这个问题。我怀疑你是对的,但我很想得到他们的开发人员的绝对确认,这是一个错误,而不是我的应用代码中的错误。 好吧,我对 node-MySQL 一无所知,但是其他连接池允许您定义一个虚拟 SQL 语句,例如“SELECT 1”,池可以使用该语句在返回之前测试连接是否仍然存在它给你。您需要调查您是否正确地完成了这项工作,或者根本没有这样做。

以上是关于MySQL 在 node.js 服务器上的空闲时间后给出“读取 ECONNRESET”错误的主要内容,如果未能解决你的问题,请参考以下文章

Heroku上的Node.js Web Socket H15空闲连接超时

重现 MySQL 错误:服务器关闭连接(node.js)

Node.js - 连接到 MySQL 数据库服务器

mysql 和 node.js 上的 AES 加密

html站点上的Node.js mysql显示表

无法使用 Node.js 和 AWS EC2 访问 mysql 服务器