Skip to main content
 首页 » 编程设计

ruby-on-rails之如何在使用 activerecords 和多线程时管理打开和关闭数据库连接

2024年02月04日13bluestorm

我正在尝试在 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 

这会在我的日志中发出警告。

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. 

它给了我一个错误

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

我尝试过: - 更改database.yaml并增加池大小和超时。 - 按以下方式修改现有代码。

   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 

我仍然收到相同的警告和错误。 我显然在这里缺少这个概念。我该如何继续?

请您参考如下方法:

为了防止多线程中的连接泄漏,您必须手动管理连接。您可以尝试:

Thread.new do 
  ActiveRecord::Base.connection_pool.with_connection do 
    # Do whatever 
  end 
end 

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