如何在使用activerecords和多个线程时管理打开和关闭数据库连接

gan*_*rey 10 activerecord multithreading ruby-on-rails

我试图在rails中实现多线程方法,以便我可以非常快速地创建/更新多个记录.

这是我的计划的大纲.

ActiveRecord::Base.transaction do
  (1..10).each do |i|
    arr[i] = Thread.new {
       <some logic on obj>
       ...
       ...
       obj.save! 
    }
  end
  arr.each {|t| t.join}
end
Run Code Online (Sandbox Code Playgroud)

这给了我日志上的警告.

DEPRECATION WARNING: Database connections will not be closed automatically, 
please close your database connection at the end of the thread by calling `close`
on your connection.
Run Code Online (Sandbox Code Playgroud)

它给了我一个错误

could not obtain a database connection within 5 seconds (waited 5.059358 seconds). 
The max pool size is currently 5; consider increasing it.
Run Code Online (Sandbox Code Playgroud)

我试过: - 更改database.yaml并增加poolize和timeout. - 以下列方式修改现有代码.

   ActiveRecord::Base.connection_pool.clear_stale_cached_connections!
   begin
     ActiveRecord::Base.transaction do
        (1..10).each do |i|
          arr[i] = Thread.new {
             <some logic on obj>
             ...
             ...
             obj.save!
             ActiveRecord::Base.connection.close 
          }
        end
        arr.each {|t| t.join}
     end
   ensure
     ActiveRecord::Base.connection.close if ActiveRecord::Base.connection
     ActiveRecord::Base.clear_active_connections!
   end
Run Code Online (Sandbox Code Playgroud)

我仍然得到相同的警告和错误.我显然在这里错过了这个概念.我该如何处理?

Blu*_*ith 22

要防止多线程中的连接泄漏,您必须手动管理连接.你可以试试:

Thread.new do
  ActiveRecord::Base.connection_pool.with_connection do
    # Do whatever
  end
end
Run Code Online (Sandbox Code Playgroud)

一个问题ActiveRecord::Base.connection_pool.with_connection是它总是准备一个连接,即使里面的代码不需要它.

我们可以通过以下方式改进它ActiveRecord::Base.connection_pool.release_connection:

Thread.new do
  begin
    # Do whatever
  ensure
    ActiveRecord::Base.connection_pool.release_connection
  end
end
Run Code Online (Sandbox Code Playgroud)