【问题标题】:ActiveRecord::StatementInvalid: Mysql::Error: MySQL server has gone away: (using the Parallel gem)ActiveRecord::StatementInvalid: Mysql::Error: MySQL server has gone away: (使用 Parallel gem)
【发布时间】:2011-03-11 06:51:29
【问题描述】:

我正在使用带有 Rails3 的 Parallel gem 并遇到 mysql 线程的问题,即使是这样的简单行:

Parallel.each(User.all, :in_processes => 1) { |r| puts r.username }

它交替工作,然后第二次失败。这是我得到的错误:

ruby-1.8.7-p330 :035 > Parallel.each(User.all, :in_processes => 1) { |r| puts r.username }
ActiveRecord::StatementInvalid: Mysql::Error: MySQL server has gone away: SELECT `users`.* FROM `users`
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/connection_adapters/abstract_adapter.rb:202:in `log'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/connection_adapters/mysql_adapter.rb:289:in `execute'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/connection_adapters/mysql_adapter.rb:619:in `select'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/connection_adapters/abstract/query_cache.rb:56:in `select_all'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/base.rb:467:in `find_by_sql'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/relation.rb:64:in `to_a'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/relation/finder_methods.rb:143:in `all'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/base.rb:439:in `__send__'
    from /Users/kimptoc/.rvm/gems/ruby-1.8.7-p330@p-ecom1-rails3/gems/activerecord-3.0.3/lib/active_record/base.rb:439:in `all'
    from (irb):35
    from (null):0

如果我做非并行版本,它工作正常:

User.all.each { |r| puts r.username }

我正在使用 mysql gem,但尝试过 mysql2 和 mysqlplus。

在 OSX 上运行。

我认为这是 ActiveRecord 和 mysql gem 如何与线程一起工作的问题。

根据我的阅读,我可能需要调整 mysql 设置以使其对并发更友好。尽管备用 gem 似乎可以更好地处理并发问题。

我已经通过 gem 提出了这个查询 - https://github.com/grosser/parallel/issues/9#comment_844380 - 但这似乎更像是一个基本问题,即如何使用 ruby​​ 设置 mysql 以进行并发访问......

所以,我的问题是 - Rails3 和 mysql 是否有明确的配置以用于并发 DB 访问?

谢谢,克里斯

编辑

似乎可行的是分成 2 个查询,一个用于获取 id,然后在循环内并行遍历 id,通过 id 重新访问实体。

ids = User.all.map { |u| u.id }
Parallel.each(ids, :in_processes => 1) do |uid| 
  ActiveRecord::Base.connection.reconnect!
  r = User.find(uid)
  puts r.username 
end

【问题讨论】:

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


    【解决方案1】:

    分叉后需要建立连接。这是分叉的一个“特性”——网络连接处于不一致的状态。

    Parallel.each(User.all, :in_processes => 1) do |r|
      ::ActiveRecord::Base.establish_connection
      puts r.username
    end
    

    【讨论】:

    • 谢谢 - 有道理,会试试看。
    • 嗯 - 仍然出现错误,我猜这是由于集合直接链接到数据库。也许我应该只提取 id 然后重新访问循环内的对象...
    【解决方案2】:

    我遇到了一个非常相似的错误,如下所示:

    pid = Process.fork
    if pid
      Process.detach(pid)
    else
      # Perform long task using ActiveRecord
      do_stuff
    end
    

    如果我在 do_stuff 运行时向服务器发送请求,它会终止任务并抛出异常:

    ActiveRecord::StatementInvalid (Mysql2::Error: Lost connection to MySQL server during query: ...
    

    添加弗朗索瓦的建议解决了我的问题:

    pid = Process.fork
    if pid
      Process.detach(pid)
    else
      # Perform long task using ActiveRecord
      ActiveRecord::Base.establish_connection
      do_stuff
    end
    

    谢谢弗朗索瓦!

    【讨论】:

      猜你喜欢
      • 2015-11-04
      • 2016-02-15
      • 1970-01-01
      • 2012-10-30
      • 2017-12-21
      • 1970-01-01
      • 2013-12-16
      • 2011-12-11
      • 2011-02-04
      相关资源
      最近更新 更多