【问题标题】:transaction in activerecord活动记录中的交易
【发布时间】:2013-02-14 20:16:57
【问题描述】:

伙计们,

我对 Rails 中的 activerecord 中的事务相当陌生,我有一段代码,我在其中执行以下操作:

transaction do
  specimen = Specimen.find_by_doc_id(25)
  specimen.state = "checking"
  specimen.save
  result = Inventory.do_check(specimen)
  if result
    specimen.state="PASS"
  else
    specimen.state="FAIL"
  end
  specimen.save
end

我在这里使用事务的目标是,如果我在 Inventory.do_check 中遇到异常(它是外部 Web 服务的客户端并执行大量 HTTP 调用和检查),那么我希望将 sample.state 回滚到它以前的值。我想知道这是否会像上面那样工作?此外,看起来在我的开发机器上,锁定是在整个 Specimen 表上设置的,当我尝试查询该表/模型时,我得到一个 BUSY 异常(我正在使用 SQLLite)。我在想应该只在那个对象/记录上设置锁。

非常感谢任何反馈,因为我说我对此很陌生,所以我的问题可能非常幼稚。

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    实现和锁定取决于数据库。我不使用 SQLLite,如果它在这种情况下锁定整个表,我不会感到惊讶。但是读取应该仍然有效,所以这可能是因为它不允许在单个连接上进行两个并发操作,所以在允许任何其他操作之前等待您的事务完成。例如,请参阅这个 SO 答案:https://stackoverflow.com/a/7154699/2117020

    但是,我的主要观点是,在任何情况下,您都不应该在访问外部服务时持有交易。然而,它是如何实现的,将事务保持几秒钟并不是您想要的。看起来在您的情况下,您想要的只是从异常中恢复。作为结果,您只是想将状态设置为“FAIL”或“initial”,还是 do_check() 修改了您的样本?如果 do_check() 没有修改样本,你最好这样做:

    specimen = Specimen.find_by_doc_id(25)
    specimen.state="checking"
    specimen.save
    # or simply specimen.update_attribute( :state, "checking" )
    
    begin
      specimen.state = Inventory.do_check(specimen) ? "PASS" : "FAIL"
    rescue
      specimen.state = "FAIL" # or "initial" or whatever
    end
    specimen.save
    

    【讨论】:

      【解决方案2】:

      锁定将高度依赖于您的数据库。您可以使用行锁。像这样的:

      specimen = Specimen.find_by_doc_id(25)
      
      success = true
      
      # reloads the record and does a select for update which locks the row until the block exits (its wrapped in a transation)
      specimen.with_lock do
        result = Inventory.do_check(specimen)
        if(result)
          specimen.state="PASS"
        else
          specimen.state="FAIL"
        end
        specimen.save!
      end
      

      在事务中检查外部站点并不理想,但是如果您使用 with_lock 并且您的数据库支持行锁,您应该只锁定这一行(它会阻塞读取,因此请谨慎使用)

      查看活动记录中的悲观锁定文档: http://ruby-docs.com/docs/ruby_1.9.3-rails_3.2.2/Rails%203.2.2/classes/ActiveRecord/Locking/Pessimistic.html

      【讨论】:

        猜你喜欢
        • 2020-02-04
        • 2015-08-27
        • 1970-01-01
        • 1970-01-01
        • 2018-06-18
        • 2011-08-18
        • 2010-10-31
        • 2014-11-19
        • 1970-01-01
        相关资源
        最近更新 更多