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