I was studying the difference between Sequel's and ActiveRecord's connection pool, and I was curious why doesn't ActiveRecord automatically release connections back into the pool after it was used for a query? Currently it stays checked out and assigned to the original thread, so other threads cannot use it, even when the original thread died.
To illustrate, the following script executes 10 queries in parallel in 10 threads, but because the pool size is 5, half of the threads will fail because they couldn't acquire a connection:
10.timesdo threads <<Thread.newdo ActiveRecord::Base.connection.execute "SELECT 1" end end
ActiveRecord::ConnectionTimeoutError: could not obtain a connection from the pool within 5.000 seconds (waited 5.003 seconds); all pooled connections were inuse
Compare that to Sequel, where everything goes just fine, since it releases connections back into the pool as soon as the query finished:
DB =Sequel.sqlite("database.sqlite3", max_connections:5)
10.timesdo threads <<Thread.newdo DB.run "SELECT 1" end end
ActiveRecord works around this limitation by requiring users to call `ActiveRecord::Base.clear_active_connections!` at the appropriate place (end of request in a web app). In Rails this is handled automatically for you (though at a surprising place – in `ActiveRecord::QueryCache.complete`), but you need to remember to do it when using ActiveRecord in other web frameworks. In Rails this started as a specialized Rack middleware called ConnectionManagement, but has since been moved into ActionDispatch::Executor middleware.
My question is whether the current connection pool behaviour is intentional (maybe there is some advantage I'm not seeing?), or it's just that no one volunteered to fix it yet?
ActiveRecord::Base.remove_connection disconnects all connections to the database. ActiveRecord might reconnect on subsequent queries, but this is not what I want, I want to reuse already open connections for performance.
To be clear, I know how to make the above code work (I can call ActiveRecord::Base.clear_active_connections!, or ActiveRecord::Base.connection_pool.with_connection with a block), what I’m challenging is that ActiveRecord shouldn’t require that you manually release connections back into the pool (like Sequel doesn’t).
threads << Thread.new do
ActiveRecord::Base.connection.execute "SELECT 1"
try also remove_connection
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/CAAwHHQhefaNNg_Pw3ywUYQqKXQBWCjET-24emFnX%2B6%2BO2xQ0RQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.