Ruby on Rails的“MySQL服务器已经消失”了

在我们的Ruby on Rails应用程序运行了一段时间后,它开始抛出500个“MySQL服务器已经消失”。 通常在一夜之间发生。 最近开始这样做,我们的服务器configuration没有明显的变化。

Mysql::Error: MySQL server has gone away: SELECT * FROM `widgets` 

重新启动mongrels(不是MySQL服务器)修复它。

我们如何解决这个问题?

这可能是由于MySQL持续连接消失(如果发生过夜,超时可能会发生),Ruby on Rails无法恢复连接,默认情况下应该这样做:

在文件vendor / rails / actionpack / lib / action_controller / dispatcher.rb是代码:

 if defined?(ActiveRecord) before_dispatch { ActiveRecord::Base.verify_active_connections! } to_prepare(:activerecord_instantiate_observers) {ActiveRecord::Base.instantiate_observers } end 

方法verify_active_connections! 执行几个操作,其中之一是重新创build任何过期的连接。

这个错误的最可能的原因是这是因为一个猴子补丁已经重新定义调度程序不要调用verify_active_connections! ,或者verify_active_connections! 已经改变了,等等

Ruby on Rails 2.3为数据库连接重新连接选项:

 production: # Your settings reconnect: true 

看到:

  • Ruby on Rails 2.3发行说明 ,分节4.8重新连接MySQL连接

  • 重新访问MySQL自动重新连接

祝你好运!

正如这个线程的其他贡献者所说,由于不活动,MySQL服务器很可能已经closures了与Ruby on Rails应用程序的连接。 默认的超时时间是28800秒,即8小时。

 set-variable = wait_timeout=86400 

将此行添加到/etc/my.cnf会将超时提高到24小时http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#option_mysqld_wait_timeout

尽pipe文档没有指出它,但值为0 可能完全禁用超时,但是您需要进行试验,因为这只是推测。

然而,我知道另外三种情况会产生这个错误。 首先是重新启动MySQL服务器。 这显然会丢掉所有的连接,但是因为MySQL客户端是被动的,所以直到下一个查询才会被注意到。

第二个条件是,如果某人从MySQL命令行中杀死了你的查询,并且这也会导致连接中断,因为它可能使客户端处于未定义的状态。

最后一个是如果你的MySQL服务器由于致命的内部错误而重新启动。 也就是说,如果你正在对表进行一个简单的查询,并立即看到“MySQL已经消失”,我会仔细看看服务器的日志,以检查硬件错误或数据库损坏。

首先,确定MySQL中的max_connections:

 show variables like "max_connections"; 

您需要确保您在Ruby on Rails应用程序中的连接数量less于允许的最大连接数。 请注意,额外的连接可以来自你的cron作业,delayed_job进程(每个在你的database.yml都有相同的池大小)等等。

在您通过应用程序时监视SQL连接,通过在MySQL中执行以下操作来运行进程等:

 show status where variable_name = 'Threads_connected'; 

您可能会考虑在Thread完成执行后closures连接,因为数据库连接不会自动closures(我认为这对Ruby on Rails 4应用程序Reaper而言不是那么重要):

 Thread.new do begin # Thread work here ensure begin if (ActiveRecord::Base.connection && ActiveRecord::Base.connection.active?) ActiveRecord::Base.connection.close end rescue end end end 

发送真正大的语句到MySQL时,我有这个问题。 MySQL会限制语句的大小,如果超过限制,将closures连接。

 set global max_allowed_packet = 1048576; # 2^20 bytes (1 MB) was enough in my case 

到MySQL服务器的连接可能超时。

你应该能够增加MySQL的超时时间,但是为了正确的修复,让你的代码检查数据库连接是否还活着,如果没有,就重新连接。

在database.yml中使用reconnect:true会导致数据库连接在ActiveRecord :: StatementInvalid错误引发后重新build立(正如Dave Cheney提到的)。

不幸的是,为了防止连接超时,在数据库操作上添加一个重试似乎是必要的:

 begin do_some_active_record_operation rescue ActiveRecord::StatementInvalid => e Rails.logger.debug("Got statement invalid #{e.message} ... trying again") # Second attempt, now that db connection is re-established do_some_active_record_operation end 

你是否监视打开的MySQL连接或线程的数量? 什么是你的mysql.ini设置max_connections?

 mysql> show status; 

查看Connections,Max_used_connections,Threads_connected和Threads_created。

您可能需要增加MySQLconfiguration中的限制,或者rails可能没有正确closures连接。

注意:我只简单地使用了Ruby on Rails …

有关服务器状态的MySQL文档位于http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html

尝试ActiveRecord::Base.connection.verify! 在Ruby on Rails中4.validation服务器是否ping通,如果没有连接,请重新连接。

其他东西要检查的是Unicornconfiguration是正确的。 在这里看到before_fork和after_fork处理ActiveRecord连接: https ://gist.github.com/nebiros/2776085#file-unicorn-rb

我在Ruby on Rails 3应用程序中使用了mysql2 gem这个问题。 我抄袭了这个有问题的查询,并试图直接在MySQL中运行它,并且我得到了同样的错误:“MySQL服务器已经消失”。

有问题的查询是非常非常大的。 一个非常大的插入(+1 MB)。 我试图插入的字段是一个TEXT列,它们的最大大小是64 KB。 而不是抛出一个错误,连接就消失了。

我增加了领域的大小,得到了同样的东西,所以我仍然不确定究竟是什么问题。 重点是,它是在数据库中,由于一些奇怪的查询。 无论如何!