【问题标题】:"MySQL server has gone away" with Ruby on RailsRuby on Rails 中的“MySQL 服务器已经消失”
【发布时间】:2010-09-11 04:00:26
【问题描述】:

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

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

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

我们如何解决这个问题?

【问题讨论】:

    标签: mysql ruby-on-rails


    【解决方案1】:

    Ruby on Rails 2.3 为您的数据库连接提供了重新连接选项:

    production:
      # Your settings
      reconnect: true
    

    见:

    祝你好运!

    【讨论】:

      【解决方案2】:

      这可能是由于与 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! 已被更改,等等。

      【讨论】:

      • 是的;我通过捕获ActiveRecord::StatementInvalid 一次并在遇到此问题时手动调用ActiveRecord::Base.verify_active_connections! 解决了这个问题。
      • @Conny,ActiveRecord::StatementInvalid 去哪儿了?在application_controller.rb?还是其他地方?
      • @ChristianFazzini,这是在一个独立的守护进程中,它服务于特定于应用程序的目的:我在一个普通的旧 Rails Web 应用程序中从未遇到过这个问题。如果我有,现在我将使用 Rails 2.3 或更新版本并使用重新连接选项as proposed by mixonic
      【解决方案3】:

      在 Ruby on Rails 4 中尝试 ActiveRecord::Base.connection.verify!。验证 ping 服务器并在未连接时重新连接。

      【讨论】:

        【解决方案4】:

        正如该线程的其他贡献者所说,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 可能完全禁用超时,但您需要进行试验,因为这只是推测。

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

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

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

        【讨论】:

        • 在我使用过的 Rails 应用程序中,我没有看到 Active Record 在当前请求期间重新连接,但它确实在下一个请求时重新连接,因此如果您可以复制一个异常,这可能是一种临时情况杂种。
        【解决方案5】:

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

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

        【讨论】:

        • 这正是我面临的问题,谢谢先生
        【解决方案6】:

        首先,确定 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';
        

        您可能需要考虑在 Thread 完成执行后关闭连接,因为数据库连接不会自动关闭(我认为这对于 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
        

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

            在 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
            

            【讨论】:

              【解决方案9】:

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

              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。

              【讨论】:

                【解决方案10】:

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

                【讨论】:

                  【解决方案11】:

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

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

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

                  【讨论】:

                  • 看我的回答——我怀疑你和我有同样的问题
                  【解决方案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

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2011-06-07
                    • 2010-12-20
                    • 2015-01-15
                    • 2016-03-06
                    • 2017-04-02
                    • 2011-11-09
                    • 2014-02-12
                    相关资源
                    最近更新 更多