2011-09-28 28 views
11

Trong lớp ảnh của tôi, tôi có liên kết này.Đường ray cách chạm vào đối tượng Active Record mà không cần khóa?

belongs_to :user, :touch => true 

Một ngày tôi có ngoại lệ này.

A ActiveRecord::StatementInvalid occurred in photos#update: 

Mysql::Error: Deadlock found when trying to get lock; try restarting transaction: 
UPDATE `users` SET `updated_at` = '2011-09-20 14:17:44' WHERE `users`.`id` = 6832 
production/ruby/1.8/gems/activerecord-3.0.10/lib/active_record/connection_adapters/abstract_adapter.rb:207:in `log' 

Tôi nên làm gì để ngăn chặn các ngoại lệ trong tương lai như điều này xảy ra? Tôi muốn báo cáo cập nhật được hiển thị trong lỗi để không sử dụng khóa nếu có thể. Tôi không nghĩ rằng bằng cách sử dụng khóa lạc quan sẽ làm việc trong trường hợp này bởi vì khóa lạc quan có lẽ sẽ nâng cao một ActiveRecord :: StaleObjectError thay thế.

Trả lời

8

Đó cũng là vấn đề mà bản thân tôi cũng gặp phải.

Câu trả lời ngắn: Không có cách nào dễ dàng để giải quyết vấn đề này. Tất cả các touch es được gói trong cùng một giao dịch, do đó bế tắc.

Câu trả lời dài: Tôi đoán bạn cần các đối tượng cảm ứng để vô hiệu hóa một số loại bộ đệm (phụ thuộc). Việc sử dụng thường được khuyến nghị là touch chỉ hoạt động với một số lượng hạn chế "mối quan hệ". Ví dụ. làm mất hiệu lực bài viết khi nhận xét đang được cập nhật.

Giải pháp của tôi là bộ sưu tập không đồng bộ (sử dụng công việc sidekiq) của đối tượng DB cần được vô hiệu. Tôi đã viết logic điều khiển của riêng mình cho nó để định nghĩa các đối tượng (khác) nào cần phải bị vô hiệu khi một đối tượng thay đổi. Ví dụ. comment ==> bài viết.

Bằng cách này, chúng tôi có cách thức chi tiết hơn cách làm mất hiệu lực đối tượng phụ thuộc. Thêm vào đó, tôi đã vô hiệu hóa bằng cách sử dụng Model.update_all, đó là cách nhanh hơn sau đó là "chuỗi liên lạc". Nó giải quyết các vấn đề bế tắc của chúng tôi (và thêm độ dài và hiệu suất vào việc hủy bỏ bộ nhớ cache của chúng tôi).

Mẹo bổ sung: Không sử dụng updated_at. Nó rất đáng tranh cãi nếu một đối tượng DB thực sự thay đổi vì một đối tượng khác thay đổi. Ghi đè mô hình cache_key cho phép bạn dễ dàng xác định khóa bộ nhớ cache tùy chỉnh như "#{id}-#{valid_from}". valid_from có thể là dấu thời gian bạn xác định trên các mô hình của mình (và bạn sử dụng thay vì updated_at).

+0

Cảm ơn câu trả lời. Đó là 2 năm sau đó và tôi không hoàn toàn chắc chắn lý do tại sao tôi đã sử dụng liên lạc. Việc vô hiệu hóa bộ nhớ cache có vẻ như là một lý do chính đáng. Bây giờ tôi sử dụng trình quét để hết hạn các mục trong bộ nhớ cache. http://guides.rubyonrails.org/caching_with_rails.html#sweepers. Tôi không dùng liên lạc ở đâu nữa. –

+0

Tôi thích ý tưởng của valid_from, nhưng tôi nghĩ rằng bạn cần phải thêm tên lớp vào cache_key là tốt, ví dụ như [class]/[id] - [timestamp] theo http://signalvnoise.com/posts/3113- các công cụ hết hạn dựa trên khóa-bộ nhớ cache – iheggie

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