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

"MySQL server has gone away" with Ruby on Rails

提问人:Gwyn Morfey 提问时间:9/19/2008 最后编辑:Peter MortensenGwyn Morfey 更新时间:5/18/2021 访问量:36232

问:

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

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

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

我们该如何解决这个问题?

MySQL 轨道上的Ruby-on-Rails

评论


答:

1赞 David Precious 9/19/2008 #1

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

您应该能够增加 MySQL 中的超时时间,但要进行适当的修复,请让您的代码检查数据库连接是否仍处于活动状态,如果不是,请重新连接。

1赞 Z99 9/19/2008 #2

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

mysql> show status;

查看连接、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

22赞 Laurie Young 9/19/2008 #3

这可能是由于与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!

此错误的最可能原因是,这是因为猴子补丁将调度程序重新定义为不调用,或者已更改等。verify_active_connections!verify_active_connections!

评论

2赞 conny 1/25/2010
是的;我通过抓住一次并在遇到此问题时手动调用来解决问题。ActiveRecord::StatementInvalidActiveRecord::Base.verify_active_connections!
0赞 Christian Fazzini 12/13/2011
@Conny,去哪儿了?在?还是其他地方?ActiveRecord::StatementInvalidapplication_controller.rb
1赞 conny 12/13/2011
@ChristianFazzini,这是在一个独立的守护进程中,它服务于特定于应用程序的目的:我从来没有在一个普通的旧 Rails Web 应用程序中遇到过这个问题。如果有的话,现在我将使用 Rails 2.3 或更高版本,并使用 mixonic 建议的重新连接选项
4赞 Dave Cheney 9/19/2008 #4

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

set-variable = wait_timeout=86400

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

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

但是,据我所知,还有其他三种情况可以产生该错误。首先是正在重新启动的MySQL服务器。这显然会断开所有连接,但由于MySQL客户端是被动的,在进行下一个查询之前不会注意到这一点。

第二个条件是,如果有人从MySQL命令行终止了您的查询,这也会断开连接,因为它可能会使客户端处于未定义状态。

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

评论

0赞 Dave Cheney 9/19/2008
在我所处理的 rails 应用程序中,我没有看到 Active Record 在当前请求期间重新连接,但它确实在下一个请求时重新连接,因此,如果您可以为每个复制一个异常,这可能是一个临时情况。
62赞 mixonic 7/24/2009 #5

Ruby on Rails 2.3 有一个用于数据库连接的重新连接选项:

production:
  # Your settings
  reconnect: true

看:

祝你好运!

1赞 Graeme Irwin 9/29/2011 #6

在 database.yml 中使用 reconnect: true 将导致在引发 ActiveRecord::StatementInvalid 错误后重新建立数据库连接(正如 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
0赞 Ryan Allen 11/22/2011 #7

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

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

我增加了字段的大小并得到了同样的东西,所以我仍然不确定确切的问题是什么。关键是,由于一些奇怪的查询,它在数据库中。无论如何!

评论

0赞 Isaac Betesh 6/2/2014
看看我的回答——我怀疑你和我一样有同样的问题
2赞 Abdo 7/26/2013 #8

首先,确定MySQL中的max_connections:

show variables like "max_connections";

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

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

show status where variable_name = 'Threads_connected';

您可能需要考虑在完成执行后关闭连接,因为数据库连接不会自动关闭(我认为这对 Ruby on Rails 4 应用程序 Reaper 来说不是问题):Thread

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
9赞 Matt Connolly 1/12/2014 #9

尝试使用 Ruby on Rails 4。验证是否对服务器执行 ping 操作,如果未连接,则重新连接。ActiveRecord::Base.connection.verify!

0赞 mahemoff 3/7/2014 #10

其他要检查的是 Unicorn 配置是否正确。请参阅此处的 ActiveRecord 连接的before_fork和after_fork处理:https://gist.github.com/nebiros/2776085#file-unicorn-rb

5赞 Isaac Betesh 5/28/2014 #11

在向MySQL发送非常大的语句时,我遇到了这个问题。MySQL限制了语句的大小,如果超过限制,将关闭连接。

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

评论

0赞 amrdruid 2/9/2021
这正是我面临的问题,谢谢先生
0赞 Joshua Pinter 5/18/2021 #12

在 Rails 中分叉时。

对于在 Rails 中分叉时遇到此问题的任何人,请尝试在分叉之前清除现有连接,然后为每个分叉建立一个新连接,如下所示:

# Clear existing connections before forking to ensure they do not get inherited.
::ActiveRecord::Base.clear_all_connections! 

fork do
  # Establish a new connection for each fork.
  ::ActiveRecord::Base.establish_connection 
  
  # The rest of the code for each fork...
end

请在此处查看此 StackOverflow 答案:https://stackoverflow.com/a/8915353/293280