我们的Ruby on Rails应用程序运行一段时间后,会突然出现500错误,并显示“MySQL server has gone away”(MySQL服务器已断开连接)的错误信息。通常情况下这种情况是在夜间发生的。但是我们的服务器配置没有明显的更改。
Mysql::Error: MySQL server has gone away: SELECT * FROM `widgets`
重新启动mongrels(而非MySQL服务器)会解决此问题。
我们该如何修复这个问题?
我们的Ruby on Rails应用程序运行一段时间后,会突然出现500错误,并显示“MySQL server has gone away”(MySQL服务器已断开连接)的错误信息。通常情况下这种情况是在夜间发生的。但是我们的服务器配置没有明显的更改。
Mysql::Error: MySQL server has gone away: SELECT * FROM `widgets`
重新启动mongrels(而非MySQL服务器)会解决此问题。
我们该如何修复这个问题?
在Ruby on Rails 2.3中,您的数据库连接有一个重新连接选项:
production:
# Your settings
reconnect: true
请参考以下内容:
祝你好运!
这可能是由于与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!
方法执行多个操作之一,其中之一是重新创建任何过期的连接。
这种错误最可能的原因是因为 monkey patch 重新定义了调度程序以不调用 verify_active_connections!
,或者 verify_active_connections!
已经被更改了等。
在Ruby on Rails 4中,尝试使用ActiveRecord::Base.connection.verify!
。Verify会向服务器发送一个测试请求,如果连接断开,则重新连接。
当向MySQL发送非常大的语句时,我遇到了这个问题。MySQL会限制语句的大小,并且如果超过限制,它将关闭连接。
set global max_allowed_packet = 1048576; # 2^20 bytes (1 MB) was enough in my case
正如这个帖子的其他贡献者所说,最有可能的是MySQL服务器由于闲置而关闭了与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。虽然文档没有说明,但是值为0可能会完全禁用超时,但需要进行实验以确定。show variables like "max_connections";
database.yml
中都有相同的池大小)等。show status where variable_name = 'Threads_connected';
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
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中增加超时时间,但为了得到一个正确的解决方案,您的代码应该检查数据库连接是否仍然存在,如果不存在则重新连接。
mysql> show status;
查看Connections、Max_used_connections、Threads_connected和Threads_created。
您可能需要在MySQL配置中增加限制,或者Rails没有正确关闭连接*。
注意:我只是简单地使用过Ruby on Rails...
有关服务器状态的MySQL文档在http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html中。
还有一件要检查的事是确保Unicorn配置正确。请在这里查看关于ActiveRecord连接的before_fork和after_fork处理:https://gist.github.com/nebiros/2776085#file-unicorn-rb
ActiveRecord::StatementInvalid
并在遇到此问题时手动调用ActiveRecord::Base.verify_active_connections!
来解决了这个问题。 - connyActiveRecord::StatementInvalid
应该放在哪里?是在application_controller.rb
吗?还是其他地方? - Christian Fazzini