在查询随机简单查询时丢失与MySQL服务器的连接

我在rails堆栈上运行ruby,我们的mysql服务器是独立的,但与我们的应用服务器位于同一站点。 (我们已经尝试将其换成不同规格的mysql服务器,但没有看到任何改进。

在工作时间,我们从没有特定查询得到一些这些。

ActiveRecord::StatementInvalid: Mysql2::Error: Lost connection to MySQL server during query 

大多数失败的查询都非常简单,并且在一个查询和另一个查询之间似乎没有模式。 这一切都是从我从Rails 4.1升级到4.2时开始的。

我不知道该尝试什么。 我们的数据库服务器全天CPU不到5%。 我确实从随机交互失败的用户那里得到了错误报告,所以这不是那些已经运行了几个小时或类似的事情的查询,当然,当他们重试它完全相同的事情时。

我们的服务器由cloud66配置。

简而言之:我们的mysql服务器由于某种原因而消失,但这不是因为缺乏资源,而是当我们从这个问题开始时从另一台服务器迁移时它也是一台全新的服务器。

在有时开发function时我也会在localhost上发生这种情况,因此我不认为这是一个负载问题。

我们正在执行以下操作:

  • ruby2.2.5
  • 铁轨4.2.6
  • mysql2 0.4.8

更新:根据下面的第一个答案,我昨晚将max_connections变量增加到500,并通过show global variables like 'max_connections';确认增加show global variables like 'max_connections';

我仍然得到连接掉线,今天第一个连接只在几分钟前被删除…. ActiveRecord::StatementInvalid: Mysql2::Error: Lost connection to MySQL server during query

select * from information_schema.processlist;运行select * from information_schema.processlist; 我有36排回来。 这是否意味着我的应用服务器当时正在运行36个连接? 或者一个过程可以是多个连接吗?

更新:我刚设置net_read_timeout = 60(之前是30)我会看看是否有帮助

更新:它没有帮助,我仍在寻找解决方案……

inheritance了我的Database.yml并删除了凭据。

 production: adapter: mysql2 encoding: utf8 host: localhost database: username: password: port: 3306 reconnect: true 

最后更新:我们通过找到一种方法来完成我们的目标,解决了这个问题。 但分叉是导致问题的原因。

与MySQL的连接可以通过多种方式中断,但我建议重新访问Mario Carrion的答案,因为这是一个非常明智的答案。

似乎连接中断,因为它与其他进程共享,导致通信协议错误……

…如果连接池是进程绑定的,这很容易发生,我相信它在ActiveRecord中,这意味着同一个连接可以在不同进程中同时“检出”多次。

解决方案是必须仅在应用程序服务器中的fork语句之后建立数据库连接。

我不确定你使用的是哪个服务器,但是如果你正在使用warmupfunction – 不要。

如果您在第一个网络请求之前运行任何数据库调用 – 请不要。

这些操作中的任何一个都可能在fork发生之前初始化连接池,导致MySQL连接池在进程之间共享,而锁定系统则不会。

我并不是说这是问题的唯一可能原因,正如@ sloth-jr所述,还有其他选择……但根据你的描述,大多数选项似乎不太可能。

边注:

我从information_schema.processlist中运行select *; 我有36排回来。 这是否意味着我的应用服务器当时正在运行36个连接? 或者一个过程可以是多个连接吗?

每个进程都可以拥有多个连接。 在您的情况下,您可能有多达500X36的连接(见编辑)

通常,池中的连接数通常与每个进程中的线程数相同(它不应小于线程数,否则争用会降低您的速度)。 有时根据您的应用程序添加更多内容是件好事。

编辑:

我为忽略流程计数引用MySQL数据而不是应用程序数据这一事实而道歉。

您显示的进程计数是MySQL服务器数据,它似乎使用每个连接IO方案的线程 。 “进程”数据实际上计算活动连接而不是实际进程或线程(尽管它也应该转换为线程数)。

这意味着每个应用程序进程可能有500个连接(即,如果您的应用程序使用8个进程,即8X500 = 4,000个允许连接),您的应用程序到目前为止只打开了36个连接。

这表示超时错误。 它通常是一般资源或连接错误。

我会在MySQL控制台上检查你的MySQL配置是否有最大连接:

 show global variables like 'max_connections'; 

并确保Rails database.yml使用的池连接数少于:

 pool: 10 

请注意,database.yml反映了单个Rails进程将池化的连接数。 如果您有多个进程或其他服务器(如Sidekiq),则需要将它们一起添加。

如果需要,在MySQL服务器配置(my.cnf)中增加max_connections,假设您的工具包可以处理它。

 [mysqld] max_connections = 100 

注意其他东西也可能阻塞,例如打开文件,但查看连接是一个很好的起点。

您还可以监控活动查询:

 select * from information_schema.processlist; 

以及监控MySQL慢日志。

一个问题可能是长时间运行的更新命令。 如果你有一个影响很多记录的慢速运行命令(例如整个表),它甚至可能阻塞最简单的查询。 这意味着您可以看到随机查询超时,但如果您检查MySQL状态,真正的原因是另一个长时间运行的查询。

你没有提到的事情,但你应该看看:

  • 你在使用独角兽吗? 如果是这样,你的after_forkbefore_fork是否重新连接和断开连接?
  • reconnect: true在您的database.yml配置中设置?

嗯,乍一看这听起来像你的网络服务器保持mysql会话打开,有时用户会遇到超时。 尝试禁用保持mysql会话活动。 这将是一头猪,但你只使用5%……

其他tipps:

祝好运!

了解您的数据库是否在多个连接方面受到限制。 因为通常SQL数据库应该有多个活动连接。 (联系您的网络提供商)

你介意发布一些问题吗? MySQL文档有这样的说法: https : //dev.mysql.com/doc/refman/5.7/en/error-lost-connection.html TL; DR:

  1. 网络问题; 您的任何一个盒子是否定期更新租约,或遇到其他网络连接错误(netstat / ss),防火墙超时等。不确定如何通过cloud66管理您的主机….
  2. 查询超时。 如果您在阻塞语句后面备份了命令(例如,在MyISAM表上更改/锁定备份),则会发生这种情况。 你的查询有多简单? 没有笛卡尔产品在玩? EXPLAIN查询可以提供帮助。
  3. 超过MAX_PACKET_SIZE。 你在存储图片,video内容等吗?

这里有很多可能性,如果没有更多信息,将难以确定这一点。

首先看看mysql_error.log,然后从数据库服务器回到你的应用程序。

更新:这不起作用。

这是解决方案,特别感谢@Myst指出分叉会导致问题,我不知道看看这个特定的代码。 由于错误似乎是随机的,因为我们在几个地方以这种方式分叉。

事实certificate,当我分叉进程时,rails对所有分叉进程使用相同的数据库连接,这创建了一种情况,当其中一个进程(父进程?)终止数据库连接时,剩下的进程将有它的连接中断。

解决方案是更改此代码:

  def recalculate_completion Process.fork do if self.course self.course.user_groups.includes(user:[:events]).each do |ug| ug.recalculate_completion end end end end 

进入这段代码:

  def recalculate_completion ActiveRecord::Base.remove_connection Process.fork do ActiveRecord::Base.establish_connection if self.course self.course.user_groups.includes(user:[:events]).each do |ug| ug.recalculate_completion end end ActiveRecord::Base.remove_connection end ActiveRecord::Base.establish_connection end 

进行此更改可以阻止来自我们服务器的错误,现在一切似乎都运行良好。 如果有人知道为什么这样有效,我会很高兴听到它,因为我希望对此有更深入的了解。

编辑:事实certificate这不起作用….我们仍然有连接断开但没有那么多。