2012-01-30 34 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