如何在Rails/ActiveRecord中的事务之外执行数据库操作

mat*_*eep 10 mysql activerecord ruby-on-rails

我需要在我的Rails应用程序中执行一些原始SQL.如果在事务中执行查询,则会导致隐式提交.我们使用MySQL和InnoDB,查询将包括例如create table.

执行查询时ActiveRecord::Base.connection.execute会触发有问题的隐含提交.

感觉我只需要一个单独的连接来执行我的查询.ActiveRecord可以提供吗?我已经看到了连接到多个数据库但没有多个连接到同一个数据库的讨论.

如果有更好的方法,解决方案不必涉及ActiveRecord.

我们的Rails和ActiveRecord版本是3.2.3.

Fre*_*ung 18

数据库连接是基于每个线程完成的(这基本上是线程安全所必需的),您可以利用它们:只需在单独的线程中执行代码,例如

ActiveRecord::Base.transaction do
  # ...
  Thread.new do
    ActiveRecord::Base.connection.execute "..." # in a new connection
  end.join
end
Run Code Online (Sandbox Code Playgroud)

从rails 4开始,activerecord不再自动获取以这种方式创建的连接.为避免泄漏连接,您需要将它们返回池中.正如马特·康奈利指出,要做到这一点最简单的方法是使用with_connection,这将在后面检查连接在块的结尾方法,例如

Thread.new do
  ActiveRecord::Base.connection_pool.with_connection do
    ...
  end
end
Run Code Online (Sandbox Code Playgroud)


Mat*_*lly 5

重要的是,如果您在线程中使用连接,则在完成后将连接返回到连接池。最简单的方法是这样的:

Thread.new do
  ActiveRecord::Base.connection_pool.with_connection do |connection|
    connection.execute "..." 
    # ensures the connection is returned to the pool when the thread is done.        
  end
end.join
Run Code Online (Sandbox Code Playgroud)