activerecord thread safey outside of rails

Hoping someone could confirm a couple of things for me.

I'm playing with activerecord/activerecord-jdbc inside jruby threads
with allow_concurrency set to true. It's creating a new connection
for each thread and appears to be working fine. Transactions appear
to be working ok also and I haven't seen any queries going into the
wrong transactions.

Anything else that might be a problem?

Chris

Hmm found one problem already, database connections are still held
open even after the thread is gone.

Chris

Yeah AR uses one connection per thread in multithreaded mode. You need to call ActiveRecord::Base.verify_active_connections! every 20 threads or so to clear out old connections. But be careful of AR in supposed thread safe mode, I've run into some really nasty issues where one thread gets its result set mixed up with results form another thread and data gets intertwined. Your best bet is to not use it in threaded mode and instead wrap a small mutex around anywhere you call AR.

  Perhaps something like this:

def use_db
   @mutex ||= Mutex.new
   @mutex.synchronize { yield }
end

use_db do
   foo = Foo.find :all
   foo.bar = 'baz;
   foo.save
end

Cheers-
-- Ezra Zygmuntowicz-- Lead Rails Evangelist
-- ez@engineyard.com
-- Engine Yard, Serious Rails Hosting
-- (866) 518-YARD (9273)

>
> Hmm found one problem already, database connections are still held
> open even after the thread is gone.
>
> Chris

        Yeah AR uses one connection per thread in multithreaded mode. You
need to call ActiveRecord::Base.verify_active_connections! every 20
threads or so to clear out old connections. But be careful of AR in
supposed thread safe mode, I've run into some really nasty issues
where one thread gets its result set mixed up with results form
another thread and data gets intertwined.

I've heard that. If you happen to have any test cases lying around
that can produce that behavior I'd love to tests it against jruby to
see if it's ar that is the problem or ruby itself.

Your best bet is to not use

it in threaded mode and instead wrap a small mutex around anywhere
you call AR.

        Perhaps something like this:

def use_db
   @mutex ||= Mutex.new
   @mutex.synchronize { yield }
end

use_db do
   foo = Foo.find :all
   foo.bar = 'baz;
   foo.save
end

Ya that works fine, I have a connection pool module that does about
the same thing. But then it blocks, and it's actually worse then just
processing each request synchronously. Instead of the requests
getting processed in the order they are received, it's too easy for
some to 'race' ahead of others to the blocking point.

Chris