【问题标题】:Rails 3.1 / mysql2 error : "MySQL server has gone away"Rails 3.1 / mysql2 错误:“MySQL 服务器已消失”
【发布时间】:2012-01-26 11:33:00
【问题描述】:

我在将我的 rails 2.3.14 / ruby​​ 1.8.7 应用升级到 3.1.1/1.9.2 时遇到问题:我有一些

(ActiveRecord::StatementInvalid) "Mysql2::Error: MySQL server has gone away"

偶尔发生错误。重要的是要准确地说,我在 2.3.14 和完全相同的 db 上从未遇到过这样的问题(因此错误不应该来自 mysql (v5.5.10))。

例子:

$ rails c production
Loading production environment (Rails 3.1.1)
ruby-1.9.2-p290 :001 > ActiveRecord::Base.connection.active?
 => false
ruby-1.9.2-p290 :002 > exit
$ rails c production
Loading production environment (Rails 3.1.1)
ruby-1.9.2-p290 :001 > ActiveRecord::Base.connection.active?
 => true 

这只发生在我的(远程)生产数据库中,我的本地开发数据库没有问题。我试图在我的 database.yml 中设置“重新连接:true”,但它导致了

Mysql2::Error: Host '****' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts':...

我尝试使用仅加载 mysql2 和 activerecord 的小 rb 脚本来隔离问题,但我没有设法以这种方式重现错误(因此它可能与 rails 堆栈相关联)。

由于编码问题(http://www.rorra.com.ar/2010/07/30/rails-3-mysql-and-utf-8/),我无法从“mysql2”返回到“mysql”gem。结果,我不得不将我的生产回滚到我的 rails 2.3.14 应用程序,这让我非常难过...

你知道我可以做些什么来调试它吗?我什至找不到重现错误的可靠方法...有人遇到过同样的错误吗?

我只是发现很少有人提到这个错误(例如:https://github.com/brianmario/mysql2/issues/213)但不是解决方案。

感谢您的帮助。

【问题讨论】:

    标签: ruby-on-rails-3 activerecord mysql2


    【解决方案1】:

    好的,我想我解决了我的问题。当我发布我的问题时,我没有注意到它,但似乎该错误与超时有关:大约 20 秒后,activerecord 失去了连接。

    $ rails runner "sleep 23; puts ActiveRecord::Base.connection.active?"
    => true
    $ rails runner "sleep 25; puts ActiveRecord::Base.connection.active?"
    => false
    

    所以我进一步挖掘,我意识到 mysql 和 mysql2 gems 并没有以相同的方式处理 MySQL 'wait_timeout' 参数:mysql gem 没有设置它,因此使用MySQL default value 28800,而mysql2 gem sets it at 2592000 如果不是在 database.yml 中定义。 但我的印象是值 2592000 超过了这个参数的最大值:2147483!这可能会导致我描述的意外行为......

    我构建了一个显示错误的脚本测试:https://gist.github.com/1514154

    如果我在加载 rails 控制台时出现了一些明显的随机断开连接(参见我的问题),我认为这是因为我的应用程序需要很长时间才能加载,而且我有时会在输入命令之前等待几秒钟。

    我无法解释为什么我们很少遇到这个问题。也许它特定于我的 conf(远程数据库,MySQL 版本?)。我尝试过使用另一个远程暂存数据库:错误没有重现...

    因此,作为结论,我将在我的 database.yml 中设置wait_timeout: 2147483。并且可能会拉取请求轨道...

    【讨论】:

    • 2147483 限制适用于 Windows,对吗?它位于“类型(Windows)”块中。对于其他平台,限制为 31536000。dev.mysql.com/doc/refman/5.5/en/…
    • 在 Windows 7 中使用 mysql2 0.3.16activerecord 4.0.0/4.1.4 进行了测试 - wait_timeout 可以正常工作,但在真正的 rails 中我遇到了连接丢失甚至内存不足的问题。
    【解决方案2】:

    有很多丢失的连接 - 但我不能说它们是否由于以下调整或其他原因而消失:/

    必须将以下脚本放入 initializers 中,并向我的 database.yml 中的每个数据库添加一行配置,如下所示:

    ...
    flags: <%= 65536 | 131072 %>
    ...
    

    脚本如下所示:

    /config/initializers/mysql2.rb

    module ActiveRecord
      class Base
        # Overriding ActiveRecord::Base.mysql2_connection
        # method to allow passing options from database.yml
        #
        # Example of database.yml
        #
        #   login: &login
        #     socket: /tmp/mysql.sock
        #     adapter: mysql2
        #     host: localhost
        #     encoding: utf8
        #     flags: 131072
        #
        # @param [Hash] config hash that you define in your
        #   database.yml
        # @return [Mysql2Adapter] new MySQL adapter object
        #
        def self.mysql2_connection(config)
          config[:username] = 'root' if config[:username].nil?
    
          if Mysql2::Client.const_defined? :FOUND_ROWS
            config[:flags] = config[:flags] ? config[:flags] | Mysql2::Client::FOUND_ROWS : Mysql2::Client::FOUND_ROWS
          end
    
          client = Mysql2::Client.new(config.symbolize_keys)
          options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
          ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
        end
      end
    end
    

    【讨论】:

    • 感谢您的回答,但我认为我们的 2 个问题不相关:您的应用程序中可能有多个语句/多个结果查询?因为您添加的标志对应于 CLIENT_MULTI_RESULTS 和 CLIENT_MULTI_STATEMENTS,不是吗?顺便说一句,使用 Mysql2::Client::MULTI_STATEMENTS 和 Mysql2::Client::PS_MULTI_RESULTS (而不是原始整数)应该可以工作。
    猜你喜欢
    • 2011-10-12
    • 2012-06-28
    • 2011-12-18
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多