MySQL 在 node.js 服务器上闲置一段时间后出现 "read ECONNRESET" 错误。

23

我正在运行一个连接到MySQL的Node服务器,通过node-mysql模块来连接。最初连接和查询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服务器以及本地设置的两者之间。

我的问题是:

  1. 这个问题似乎是由于Node与我的MySQL服务器的连接断开引起的,可能是由于连接寿命限制?

  2. 使用连接池时,node-mysql应该优雅地处理断开连接并将其从池中删除。它直到我进行查询才意识到它已经断开连接,因此使错误不可避免吗?

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

更新:经过更多浏览,我认为我的问题是这个问题的重复。他的连接也会断开,但没有人建议如何保持连接活动或如何在第一个查询失败之外解决错误。

4个回答

22

我联系了node-mysql的相关人员,在他们的Github页面上得到了一些明确的答案。

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

  2. 根据此问题所述,node-mysql在此类断开连接后不会修剪池连接。模块开发人员建议使用心跳来保持连接活动,如在间隔上调用SELECT 1;。他们还建议使用node-pool模块及其idleTimeoutMillis选项自动修剪空闲连接。


你的问题和答案真的帮了我很多。你有尝试过使用node-pool模块吗?或许你有具体的例子可以分享吗? - Yuval A.
在/etc/my.cnf中添加wait_timeout=28800;这个起作用 :-) - Jan Bludau

11
如果在建立单个重用连接时出现这种情况,可以通过建立连接池来避免。
例如,如果您正在执行以下操作...
var db = require('mysql')
  .createConnection({...})
  .connect(function(err){});

那么,不要这样做,而要这样做...

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

1
无论是使用单个连接还是连接池,我仍然遇到了这个问题。正如我接受的答案所概述的那样,这是MySQL挂起并且node-mysql没有意识到的症状。自那以后已经过了很多年,这个问题可能已经被修复了。 - Brent Traut
2
谢谢你的见解。最近我遇到了同样的错误,然后在使用连接池后问题得到了解决。因此,我发布了这篇文章,希望能帮助到其他遇到同样问题的人。 - Ben Thielker

1
这个问题是否是由于连接寿命限制,导致Node与我的MySQL服务器之间的连接断开了呢?
是的。服务器已经关闭了它的连接端口。
当使用连接池时,node-mysql应该优雅地处理断开连接并将其从池中删除。但是,它是否直到我发出查询才意识到连接已断开,从而使错误不可避免?
是的,但它应该在内部处理错误,而不是将其传递给您。这似乎是node-mysql中的一个bug。请报告它。
考虑到我在其他StackOverflow帖子中经常看到“read ECONNRESET”错误,我是否应该从MySQL以外的地方来诊断问题?
要么是node-MySQL连接池实现中的一个bug,要么是您没有正确配置它来检测故障。

谢谢!我已经在node-mysql的Github页面上报告了这个问题。我怀疑你是对的,但我希望能从他们的开发人员那里得到绝对的确认,这不是我的应用程序代码中的错误,而是一个bug。 - Brent Traut
我对node-MySQL一无所知,但其他连接池允许您定义一个虚拟的SQL语句,例如“SELECT 1”,以便连接池在将连接返回给您之前测试连接是否仍然有效。您需要调查是否已经正确地执行了这个步骤,或者是否根本没有执行。 - user207421
差不多十年过去了,但问题似乎仍然存在。为了正确模拟它,我不得不在我的开发机上设置一个较短的等待超时值。为了避免这个问题,我所要做的就是在使用完连接后立即关闭它。 - undefined

0

我也遇到了同样的问题。显然这是因为其中一个后端进程被触发在被我的API引用的表上。

这导致表处于锁定等待状态,我的查询请求因连接复位而失败。尽管我想知道为什么我没有收到锁定等待错误。


目前你的回答不够清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接