簡體   English   中英

活動記錄中的交易

[英]transaction in activerecord

民間,

我對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回滾到其先前的值。 我想知道這樣是否可以正常工作? 同樣,在我的開發機器上,鎖似乎是在整個“標本”表上設置的,當我嘗試查詢該表/模型時,我遇到了“忙”異常(我正在使用SQLLite)。 我以為只能在該對象/記錄上設置鎖定。

非常感謝任何反饋,因為我說過我真的很陌生,所以我的問題可能很幼稚。

實現和鎖定取決於數據庫。 我不使用SQLLite,並且在這種情況下鎖定整個表也不會感到驚訝。 但是讀取仍然可以工作,因此可能是因為它不允許在單個連接上執行兩個並發操作,因此在允許任何其他操作之前等待事務完成。 例如,請參見以下SO答案: https : //stackoverflow.com/a/7154699/2117020

但是,我的主要觀點是,無論如何在訪問外部服務時都不應該暫停事務。 不管它實現了多少秒,這都不是您想要的。 在您的情況下,看起來您想要的只是從異常中恢復。 您是否只是想將狀態設置為“失敗”或“初始”,還是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

鎖定將高度依賴於您的數據庫。 您可以使用行鎖。 像這樣:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM