This project is archived and is in readonly mode.
connections not released in rails 3
Reported by luis.lopez (at branelabs) | September 29th, 2010 @ 09:27 PM
When a activerecord asks for a connection in a thread, this connections is not released after thread end. So, the connection pool can be exhausted. Definining a pool of 5 for the DB connection (mysql), this code fails after the 5th try:
puts "ruby vesion: #{RUBY_VERSION} rails version: #{Rails.version}"
1.upto(10) do |i|
Thread.new() do
puts "iteration #{i}"
User.first
puts "iteration #{i} after query"
# ActiveRecord::Base.connection_pool.release_connection
end.join
# ActiveRecord::Base.connection_pool.clear_stale_cached_connections!()
end
the result is:
$rails runner /tmp/test2.rb ruby vesion: 1.9.2 rails version: 3.0.0 iteration 1 iteration 1 after query iteration 2 iteration 2 after query iteration 3 iteration 3 after query iteration 4 iteration 4 after query iteration 5 iteration 5 after query iteration 6 /tmp/test2.rb:4:in
join': deadlock detected (fatal)</code> </pre>
Uncommenting one of the commented lines that manually forces to release connections makes it works but I guess it's not the expected behaviour since it worked without problems in previous version (tested with ruby 1.8.7 and rails 2.3.5)
It fails too with rails 3.1.0.beta.
Comments and changes to this ticket
-
Hemant Kumar September 30th, 2010 @ 10:08 AM
- Assigned user set to Aaron Patterson
Verified on Ruby 1.9. The problem with checkout methods is, it relies on return value of
wait
method to reclaim connections from dead threads.But return value of
wait
has been changed and in 1.9 it will return always true, whether it returns aftertimeout
period or it returns because it was signalled bysingal
. In fact, return value ofwait
can't be relied upon and I saw the code of Rubinius and JRuby implementations as well and behaviour is not analogous to 1.8.Attached patch fixes the problem and it no longer depends on return value of
wait
method. I have also added some missing tests. One more thing that I did ended up doing was settingtimeout
value on1.9
; original code hadtimeout
set tonil
in Ruby 1.9. Callingwait
withnil
parameter can trigger deadlock as OP got in original bug report. -
Hemant Kumar September 30th, 2010 @ 10:19 AM
- Tag changed from rails 3.0.0, connection, pool, thread to rails 3.0.0, connection, patched, pool, thread
-
luis.lopez (at branelabs) September 30th, 2010 @ 12:06 PM
- Tag cleared.
The patch works. The only drawback is the waiting time to release connections. If you run the above code, it will freeze for 5 seconds in the 6th try. If you do the test more times (1.upto(20), for instance) it will freeze 5 seconds every 5 tries (since the pool is 5 for this test). Not sure if it is possible to check if there are connections to be reclaimed before wait.
-
gnufied September 30th, 2010 @ 02:07 PM
Well the patch does not modify original behaviour, it just makes it work on Ruby 1.9. One can of course check for connections held by dead threads before calling
wait
,but that would mean that we will have to callclear_stale_cached_connections
twice:clear_stale_cached_connections! if(@checked_out.size < @connections.size) next else @queue.wait(@timeout) end clear_stale_cached_connections! if @size == @checked_out.size raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it." end
-
luis.lopez (at branelabs) September 30th, 2010 @ 05:18 PM
I personally think that it would be a better solution: the best moment to check for connections is probably before the wait and I don't think that call clear_stale_cached_connections twice would be big problem since there is a wait anyway. In the worst case there will be 2 calls to clear_stale_cached_connections (one more then in the current code) and in the best the wait would be avoided.
However, I don't know if clear_stale_cached_connections! could have a big performance penalty in case the pool were big
-
Repository October 6th, 2010 @ 09:43 PM
- State changed from new to committed
(from [444aa9c7350f243a6b4b2a3ff1601493a812872a]) fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests http://github.com/rails/rails/commit/444aa9c7350f243a6b4b2a3ff16014...
-
Repository October 6th, 2010 @ 09:46 PM
(from [2a04110f266b6ccaf94aeeae224af578a9620fbd]) fix ruby 1.9 deadlock problem, fixes #5736 add connection pool tests http://github.com/rails/rails/commit/2a04110f266b6ccaf94aeeae224af5...
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>
People watching this ticket
Attachments
Referenced by
- 6714 Active Record connection pool Rails 3.0.6 There was a issue filed before #5736, I think the issue i...
- 5736 connections not released in rails 3 (from [444aa9c7350f243a6b4b2a3ff1601493a812872a]) fix rub...
- 5736 connections not released in rails 3 (from [2a04110f266b6ccaf94aeeae224af578a9620fbd]) fix rub...