I need to execute some raw SQL in my Rails app. The query will do cause an implicit commit if it is performed within a transaction. We are using MySQL with InnoDB and the query will include e.g. create table.
Executing the query with ActiveRecord::Base.connection.execute
triggers the implict commit which is a problem.
It feels like I just need a separate connection for performing my queries. Can ActiveRecord provide this? I've seen discussions of connecting to multiple databases but not multiple connections to the same database.
A solution doesn't have to involve ActiveRecord if there's a better way.
Our Rails and ActiveRecord version is 3.2.3.
Transactions in ActiveRecordEvery database operation that happens inside that block will be sent to the database as a transaction. If any kind of unhandled error happens inside the block, the transaction will be aborted, and no changes will be made to the DB.
ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending. Edit: as Mike points out, in this case ActiveRecord is a module...
ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code.
Database connections are done on a per thread basis (this is basically required for thread safety), which you can use to your advantage: just execute your code in a separate thread, for example
ActiveRecord::Base.transaction do
# ...
Thread.new do
ActiveRecord::Base.connection.execute "..." # in a new connection
end.join
end
As of rails 4, activerecord no longer reaps connections created in this way automatically. To avoid leaking connections you need to return them to the pool. As Matt Connelly suggests, the easiest way to do this is to use the with_connection
method which will check the connection back in at the end of the block, for example
Thread.new do
ActiveRecord::Base.connection_pool.with_connection do
...
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With