2012-01-30 38 views
47

Trong nhật ký, tôi thấy ROLLBACK, nhưng không có ngoại lệ nào được ghi lại. Có cách nào để tìm hiểu nguyên nhân gây ra ROLLBACK không?cách tìm nguyên nhân của ActiveRecord ROLLBACK

Dưới đây là đoạn trích của các bản ghi:

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

Có gì trong nhật ký xung quanh ROLLBACK? –

+1

Không có lỗi. Ngoài ra, nó là lạ rằng một thời gian nó sử dụng một giao dịch, lần sau nó không. Trừ khi hai mảnh đó không liên quan. – m33lky

+0

Bất kỳ ý tưởng nào gây ra SELECT trong giao dịch? –

Trả lời

46

Một cách là để tự ghi thông tin để đăng nhập. Hãy thử một cái gì đó như thế này từ bộ điều khiển của bạn:

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

Điều đó sẽ xuất nội dung của tất cả các xác thực không thành công.

7

3 phương pháp (1 thất bại) Tôi đã đưa ra là để

1) sử dụng một người quan sát trong lịch sử hoạt động trên tất cả các lưu, xác nhận phương pháp có liên quan

2) để mở ra kỷ lục hoạt động và đặt câu lệnh trình gỡ rối trong đó ROLLBACK được kích hoạt và sau đó chạy caller để xác định mã đã kích hoạt lỗi.

3) Không thành công: ghi đè các phương thức ghi đang hoạt động và tạm dừng ngoại lệ. Nếu tôi nhớ phương pháp này không bắt bất kỳ ngoại lệ nào vì các phương thức lưu được gói trong một giao dịch.

Ghi chú: Chỉ bật khi chế độ không phải là Rails.env.production ?. Thử nghiệm trên Rails 3.2.13, sử dụng ruby ​​1.9.3.

1) Observer: 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 'bó chương 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) 

Khi máy chủ ray hoặc console lượt truy cập các loại breakpoint trong caller để có được những vết lùi .

3) Ghi đè AR trong chế độ phát triển. TODO: chỉ ghi đè nếu! Rails.env.production? Đặt này trong 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) Vô hiệu hoá before_create, before_save, before_update và kiểm tra nơi nó tiết kiệm ngày

2) Nếu khôi phục được gây ra bởi một trong các phương pháp đó, kiểm tra xem các phương pháp đó trở lại đúng khi bạn không có kế hoạch quay trở lại.

Ví dụ, nếu bạn đặt giá trị mặc định cho trường boolean để tránh con số không, có thể bạn sẽ làm theo cách

def set_defaults_before_create 
    self.my_boolean_field ||= false 
end 

này Trong ví dụ phương pháp này set_defaults_before_create luôn trả sai và do đó rollbacks giao dịch của bạn. Vì vậy, hãy cấu trúc lại để trả về true

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

Đó là một vấn đề tinh tế, cảm ơn vì đã chỉ ra nó! – vemv

+1

bạn rất hoan nghênh @vemv –

+2

Tôi đã dành khoảng một ngày cố gắng gỡ lỗi vấn đề này. Cảm ơn rất nhiều:) – Subtletree

62

lưu bản ghi với BANG '!'vì vậy nó sẽ làm cho một lỗi thời gian chạy và bạn sẽ biết nó xảy ra ở đâu

+10

Điều này phải được đánh dấu là câu trả lời. – wuliwong

+0

Tôi không biết. Trong trường hợp của tôi, tôi nhận được một ROLLBACK trên một 'phá hủy' trong trường hợp đó câu trả lời được chọn có vẻ như giúp tôi nhưng câu trả lời này không áp dụng. –

+0

Tôi ước tôi có thể upvote nhiều lần này. Nó đã cứu tôi nhiều lần. – BigRon

Các vấn đề liên quan