Rails 2.2 Connection Pools + Mongrel Handlers = Slow

Rails 2.2 doesn’t like Mongrel handlers. Specifically, the Rails 2.2 connection pool doesn’t. More specifically, the connection pool doesn’t like a bunch of random threads taking its connections and not giving them back.

After a day of head banging (yah!! rock on!!), I devised the following monkey patch solution to get our Mongrel handlers back on Rails’ good graces:

module ActiveRecord
module ConnectionAdapters
class ConnectionPool
def release_connection(conn_id = nil)
conn_id ||= current_connection_id
conn = @reserved_connections.delete(conn_id)
checkin conn if conn
end
end

class ConnectionHandler
def clear_my_connection!(conn_id)
@connection_pools.each_value {|pool| pool.release_connection(conn_id) }
end
end
end
end

After you paste that into a file in your initializers directory, you’ll just need to call the clear_my_connection! method whenever you exit a Mongrel handler (or other type of Rails thread) that has accessed an ActiveRecord find. We’re doing this like so:

ActiveRecord::Base.connection_handler.clear_my_connection!(Thread.current.object_id)

Hope this saves someone else a day of unproductive Googling when they upgrade to 2.2 and their Mongrel handlers suddenly start taking 5 seconds each (the time until the Thread’s connection will naturally timeout) to execute.

If anyone else has solved this in a more elegant way, you speak up now, y’hear?

3 Replies to “Rails 2.2 Connection Pools + Mongrel Handlers = Slow”

  1. Hi,

    thanks for sharing this. I’m having the same kind of issue while using ActiveRecord 2.2.2 outside Rails (in multithreaded Ramaze): the n-1 first queries (with n = activerecord pool size) are fast, then the n-th query shows 2 thread and runs during 5 seconds.

    I’ll try applying what you did.

    Did you came up with something else since you wrote this ?

    cheers

    — Thibaut

  2. Working under Rails2.3 (with Rails::Metal) I got the same issue.

    It’s in the documentation of ActiveRecord, you have to manualy release the connection that ActiveRecord fetch from the pool when you no longer need them (at the end of the Rack process).

    So I just implemented a Rack Middleware to free them, it is a bit cleaner but does exactly the same thing (or rather make ActiveRecord do the same thing) and can be reused in any kind of rack stack using active record

    http://gist.github.com/57640

    Otherwise in current ActiveRecord version you could just drop your code and execute ActiveRecord::Base.clear_active_connections! when you want to release the connection into the pool. It does the same stuff than you patch.

  3. I’m working on an XMPP server where each client gets it’s own thread for the length of the connection that could be hours or more. I noticed that ActiveRecord started failing at around 5 connections with long waits or timeouts during Authentication where it would look at the appropriate user/pass in the database. A quick DTrace/Instruments session pointed to it blocking until a connection from the pool is available.

    Renaud explained it above: Since each thread is still alive, ActiveRecord keeps that pool record alive. Manually releasing the connection back to the pool after each major stanza point with your monkeypatch fixed the issue.

Leave a Reply

Your email address will not be published. Required fields are marked *