2012-01-30 35 views
47

在日誌中我看到一個ROLLBACK,但沒有記錄異常。有沒有辦法找出造成ROLLBACK的原因?如何找到ActiveRecord的原因ROLLBACK

這裏的日誌摘錄:

Phone Load (0.4ms) SELECT "phones".* FROM "phones" WHERE "phones"."id" = $1 LIMIT 1 [["id", 980190963]] 
    (0.2ms) BEGIN 
    User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."phone_id" = 980190963 LIMIT 1 
    (0.2ms) ROLLBACK 
    Phone Load (0.4ms) SELECT "phones".* FROM "phones" WHERE "phones"."id" = $1 LIMIT 1 [["id", 980190963]] 
    User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."phone_id" = 980190963 LIMIT 1 
+1

ROLLBACK的日誌是什麼? – 2012-01-30 06:26:28

+1

沒有錯誤。另外,有一次它使用了一個事務,而下一次它沒有使用它,這很奇怪。除非這兩件事是無關的。 – m33lky 2012-01-30 07:23:12

+0

任何想法是什麼導致事務內的SELECT? – 2012-01-30 07:32:59

回答

46

一種方式是手工信息寫入日誌。嘗試從你的控制器這樣的事情:

Rails.logger.info(@your_object.errors.inspect) 

這應該輸出所有驗證失敗的內容。

7

的3種方法(1失敗)我想出了要

1)使用上的活動記錄觀察者對所有相關的保存,驗證方法

2)開拓活動記錄和在觸發ROLLBACKs的地方放置一個調試器語句,然後運行caller來查明觸發錯誤的代碼。

3)失敗:覆蓋活動記錄方法並暫停異常。如果我記得這個方法沒有捕獲任何異常,因爲保存方法被封裝在一個事務中。

注意:只有當模式不是Rails.env.production時才啓用。測試Rails 3.2.13,使用紅寶石1.9.3。

1)觀察報:http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#observers

class ActiveRecordObserver < ActiveRecord::Observer 

    observe "ActiveRecord::Base" 

    def after_validation(model) 
     debugger if model.errors.messages.any? 
     Rails.logger.error "after validation" 
    end 
    def before_update(model) 
     debugger if !model.valid? 
     Rails.logger.error "before update" 
    end 
    def after_update(model) 
     debugger if !model.valid? 
     Rails.logger.error "after update" 
    end 
    def before_save(model) 

     debugger if model.errors.messages.any? 
     Rails.logger.error "#{model}" Rails.logger.error "before save" 
    end 
    def after_save(model) 
     debugger if model.errors.messages.any? 
     Rails.logger.error "after save" 
    end 
end 

2) https://github.com/rails/rails/blob/3-1-stable/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb#L231 CD`束秀activerecord`

 Put a debugger statement when where the rollback is executed. 
    /Users/<user>/.rvm/gems/ruby-1.9.3-<env>/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract/database_statements.rb 

    196    transaction_open = false 
    197    decrement_open_transactions 
    198    if open_transactions == 0 
    199    rollback_db_transaction 
    200    debugger 
=> 201    rollback_transaction_records(true) 
    202    else 
    203    rollback_to_savepoint 
    204    debugger 
    205    rollback_transaction_records(false) 

當軌道服務器或控制檯caller命中斷點類型,以獲得回溯。

3)在開發模式下重寫AR。 TODO:只有在!Rails.env.production時纔會覆蓋? 在app/config/initializers/active_record_or_any_file_name.rb

ActiveRecord::Base.class_eval do 
    alias_method :old_save, :save 
    alias_method :old_save!, :save! 
    def save(*args) 
     begin 
      puts "#{self} save" 
      Rails.logger.info "#{self} save" 
      old_save(*args) 
     rescue Exception => e 
      debugger 
      puts e 
     end 
    end 
    def save!(*args) 
     begin 
      Rails.logger.info "#{self} save!" 
      puts "#{self} save!" 
      old_save!(*args) 
     rescue Exception => e 
      debugger 
      puts e 
     end 
    end 
end 
19

1)禁止before_create將這個,before_save,before_update,並檢查它可以節省如果回滾是由這些方法之一引起了一天

2),檢查那些方法返回如果您不打算回滾,則爲true。

例如,如果你布爾字段設置默認值,以避免零,你可能會做這樣

def set_defaults_before_create 
    self.my_boolean_field ||= false 
end 

在這個例子方法set_defaults_before_create總是返回,從而回滾事務。所以重構它返回true

def set_defaults_before_create 
    self.my_boolean_field ||= false 
    true 
end 
+4

這是一個微妙的問題,謝謝指出! – vemv 2013-11-06 12:38:14

+1

非常歡迎@vemv – 2013-12-17 09:31:10

+2

我花了大概一天的時間試圖調試這個問題。非常感謝:) – Subtletree 2014-04-17 02:20:02

62

保存記錄與邦'!'所以這會造成運行時間錯誤,並且您會知道它發生了什麼

+10

這應該被標記爲答案。 – wuliwong 2015-07-08 21:50:52

+0

我不知道。在我的情況下,我在'destroy'上得到了一個ROLLBACK,在這種情況下,所選答案似乎對我有幫助,但這個不適用。 – 2016-07-21 14:20:18

+0

我希望我可以多次使用它。它多次救了我。 – BigRon 2017-07-15 12:44:35