Rails 3.1 / mysql2 错误:“MySQL 服务器已消失”

发布于 2024-12-22 16:38:41 字数 1415 浏览 5 评论 0 原文

我在将 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 上的“mysql”gem 和完全相同的数据库上从未遇到过此类问题(因此该错误不应来自 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中设置“reconnect:true”,但这导致了

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

我试图用一个仅加载mysql2和activerecord的小rb脚本来隔离问题,但我没有设法重现该错误方式(因此它可能链接到 Rails 堆栈)。

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

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

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

感谢您的帮助。

I'm experiencing trouble upgrading my rails 2.3.14 / ruby 1.8.7 app to 3.1.1/1.9.2 : I have some

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

errors happening sporadically. It's important to precise that I never had such issues with the 'mysql' gem on 2.3.14 and the exactly same db (so the bug shouldn't come from mysql (v5.5.10)).

Example :

$ 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 

This happens only with my (remote) production database, no problem with my local development db. I've tried to set "reconnect: true" in my database.yml but it led to a

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

I've tried to isolate the problem with a little rb script only loading mysql2 and activerecord but I didn't manage to reproduce the bug that way (so it may be linked to the rails stack).

I can't go back from the 'mysql2' to the 'mysql' gem because of encoding issues ( http://www.rorra.com.ar/2010/07/30/rails-3-mysql-and-utf-8/ ). As a consequence, I had to rollback my production to my rails 2.3.14 app, which saddens me very much...

Do you see what I can do to debug this ? I can't even find a sure way to reproduce the error... Have anyone met the same bug ?

I just found few people mentionning this bug (ex : https://github.com/brianmario/mysql2/issues/213) but not a solution.

Thanks for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

神经大条 2024-12-29 16:38:41

好吧,我想我解决了我的问题。当我发布我的问题时,我没有注意到它,但似乎该错误与超时相关:大约 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 默认值 28800,而 如果数据库中未定义,mysql2 gem 将其设置为 2592000 .yml。
但我的印象是值 2592000 超过了该参数的最大值:

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

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

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

因此作为结论,我将在我的database.yml中设置wait_timeout: 2147483。也许拉请求轨道......

Ok, I think I solved my problem. I didn't notice it when I posted my question, but it seemed that the error was timeout related : after about 20s, activerecord losts its connection.

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

So I dug further and I realized that mysql and mysql2 gems didn't deal with the MySQL 'wait_timeout' param the same way : mysql gem doesn't set it thus uses the MySQL default value 28800, whereas mysql2 gem sets it at 2592000 if not defined in the database.yml.
But I have the impression that the value 2592000 is over the max value for this param : 2147483 ! Which could lead to the unexpected behavior I described...

I build a script test showing the bug : https://gist.github.com/1514154

And if I had some apparently random disconnect while loading rails console (cf my question), I think it's because of my app taking a long time to load and me sometimes waiting a few seconds before typing my command.

I can't explain why we are so few to encounter this problem. Perhaps it's specific to my conf (remote database, MySQL version ?). I've tried with another remote staging database : the bug didn't reproduce...

So as a conclusion, I will set wait_timeout: 2147483 in my database.yml. And maybe pull request rails...

榆西 2024-12-29 16:38:41

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

必须将以下脚本放入初始化器中,并为每个连接添加一行配置我的 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

Had a lot of lost connections - but I couldn't say if they went away due to the following tweak or elsewise :/

Had to throw the following script into initializers and add a line of configuration to each of my databases in my database.yml like this:

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

The script looks like this:

/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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文