2012-12-10 66 views
2

我有一個軌道應用程序,我崩潰的目的..它是本地的,我只是擊中Ctrl + C和通過處理記錄中途殺死它..rails activerecord事務塊似乎並沒有提交

在我看來,塊中的記錄不應該被提交..這是一個postgres的「錯誤」或軌道「錯誤」,或戴夫錯誤?

 ActiveRecord::Base.transaction do 
     UploadStage.where("id in (#{ids.join(',')})").update_all(:status => 2); 

     records.each do |record| 
      record.success = process_line(record.id, klas, record.hash_value).to_s[0..250] 
      record.status = 1000 
      record.save(); 
     end  
     end 

我生成我的ID通過讀出所有的記錄中,其中狀態爲1
沒有什麼,但這個功能將狀態設置爲1000 ..

如果動作崩潰了什麼都原因,我預計在狀態= 2的數據庫中沒有記錄... 這並不是我所看到的。一半的記錄有狀態1000,另一半有狀態2 ..。

我錯過了什麼嗎?
如果應用程序崩潰,我如何確保沒有2?


編輯:
我發現這個鏈接http://coderrr.wordpress.com/2011/05/03/beware-of-threadkill-or-your-activerecord-transactions-are-in-danger-of-being-partially-committed/

+2

考慮啓用詳細的查詢記錄並查看Rails正在做什麼。在'postgresql.conf'中使用'log_statement ='all'',然後檢查PostgreSQL日誌。當你展示的是Rails代碼時,如果這是PostgreSQL的問題是不可能的,但我會驚訝的發現; ActiveRecord是一個奇怪而古怪的野獸,而PostgreSQL的交易代碼已經非常成熟並且經過了充分的測試。就個人而言,如果ActiveRecord在得到終止信號時「有用」地提交交易,我不會感到驚訝。 –

+0

如果你殺死-9'(即SIGKILL)會發生什麼? Ctrl + C是一種非常溫和的關閉方式,Rails可能會將其解釋爲「一旦我正在執行的任何操作都已完成,就停止接受新的關聯關閉」。 –

+0

當然...如果我走過服務器並在電源線上絆倒,會發生什麼情況..我試圖模擬非正常的崩潰...... ctrl + c與我現在需要測試的距離一樣近。 ..因爲它失敗了,我想我會先修好它。 – baash05

回答

1

正如我懷疑和戴夫的更新所證實,它看起來像ActiveRecord的會在某些情況下犯下半成品的交易,當你殺死一個線程。喔,安全!有關詳細說明和緩解選項,請參閱dave's link

如果你正在模擬硬件崩潰(主機操作系統崩潰或插拔),control-C絕對不是正確的方法。使用Control-\發送一個SIGQUIT(通常不會處理),或使用kill -KILL來硬拷貝該進程而沒有機會進行清理。 Control-C發送SIGINT這是一個溫和的信號,通常附加到乾淨的關機處理程序。

一般來說,如果你正在調試這樣的問題,你應該啓用詳細的查詢記錄,看看Rails正在做什麼。在postgresql.conf中使用log_statement = 'all'然後檢查PostgreSQL日誌。