Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage opening and closing database connections while working with activerecords and multiple threads

I am trying to implement a multithreaded method in rails such that I can create/update multiple records very quickly.

This is the outline of my program.

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

This gives me warnings on my log.

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.

And it gives me an error

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

I tried: - changing database.yaml and increasing the poolsize and timeout there. - modified the existing code in the following way.

   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

I am still getting the same warning and error. I am obviously missing the concept here. How do I proceed with this?

like image 447
gandalf_grey Avatar asked May 11 '14 18:05

gandalf_grey


People also ask

When should you open and close a database connection?

If you have a valid reason to keep it open, then do so. If not, close it as soon as you're done with it. But it's better to be in the good habit of closing the connections so that you don't just leave them open when you don't intend to.

Why should you make sure you always close out your database connection?

For the purpose of safe coding, you should always close database connections explicitly to make sure that the code was able to close itself gracefully and to prevent any other objects from reusing the same connection after you are done with it.

Can rails connect to multiple databases?

Rails now has support for multiple databases so you don't have to store your data all in one place. At this time the following features are supported: Multiple writer databases and a replica for each. Automatic connection switching for the model you're working with.


1 Answers

To prevent connection leak in multi threads, you have to manage the connection manually. You can try:

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

One problem of ActiveRecord::Base.connection_pool.with_connection is that it always prepare a connection even if the code inside does not need it.

We can improve it a little bit by using ActiveRecord::Base.connection_pool.release_connection:

Thread.new do
  begin
    # Do whatever
  ensure
    ActiveRecord::Base.connection_pool.release_connection
  end
end
like image 59
Blue Smith Avatar answered Oct 25 '22 10:10

Blue Smith