【问题标题】:How can I execute a Database Operation outside of a transaction in Rails / ActiveRecord如何在 Rails / ActiveRecord 中的事务之外执行数据库操作
【发布时间】:2012-07-26 17:10:23
【问题描述】:

我需要在我的 Rails 应用程序中执行一些原始 SQL。如果在事务中执行查询,它会导致隐式提交。我们将 MySQL 与 InnoDB 一起使用,查询将包括例如创建表。

使用ActiveRecord::Base.connection.execute 执行查询会触发隐式提交,这是一个问题。

感觉就像我只需要一个单独的连接来执行我的查询。 ActiveRecord 可以提供这个吗?我见过关于连接到多个数据库而不是多个连接到同一个数据库的讨论。

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

我们的 Rails 和 ActiveRecord 版本是 3.2.3。

【问题讨论】:

    标签: mysql ruby-on-rails activerecord


    【解决方案1】:

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

    ActiveRecord::Base.transaction do
      # ...
      Thread.new do
        ActiveRecord::Base.connection.execute "..." # in a new connection
      end.join
    end
    

    从 rails 4 开始,activerecord 不再自动获取以这种方式创建的连接。为了避免泄漏连接,您需要将它们返回到池中。正如 Matt Connelly 建议的那样,最简单的方法是使用 with_connection 方法,该方法将在块末尾检查连接,例如

    Thread.new do
      ActiveRecord::Base.connection_pool.with_connection do
        ...
      end
    end
    

    【讨论】:

    • 我想你更好地理解了这个问题:)
    • 确保在完成后将连接返回到连接池!
    【解决方案2】:

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

    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
    

    【讨论】:

      【解决方案3】:

      DDl 和其他一些查询会触发隐式提交,因此它们不能按照 mysql 文档回滚

      http://dev.mysql.com/doc/refman/5.1/en/implicit-commit.html

      这些隐式结束当前会话中活动的任何事务,就像您在执行语句之前完成了 COMMIT 一样。

      如果中间没有这样的查询,那么您可以使用 SAVEPOINT 功能。 (This does not work with DDL statements)

      活动记录中有一个选项可以帮助创建使用保存点的子事务

         ActiveRecord::Base.transaction do
           # ...
         ActiveRecord::Base.transaction(:requires_new => true) do #creates save point
             # perform task 
             # if error occurs rollbacks only till the save point.
           end
         end
      

      查看rails doc了解更多详情。

      【讨论】:

      • 作者说的是总是隐式提交事务的语句(例如alter table)
      • @FrederickCheung,来自问题“ActiveRecord::Base.connection.execute 触发隐含提交,这是一个问题。”让我相信他想自己明确控制交易。有错请指正
      猜你喜欢
      • 1970-01-01
      • 2015-09-15
      • 2013-10-12
      • 2014-04-01
      • 2011-11-02
      • 2011-10-05
      • 1970-01-01
      • 1970-01-01
      • 2012-07-11
      相关资源
      最近更新 更多