Eri*_*ard 11 caching locking ruby-on-rails associations touch
在我的照片课上,我有这种关联.
belongs_to :user, :touch => true
Run Code Online (Sandbox Code Playgroud)
有一天我得到了这个例外.
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'
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能防止此类事件发生?我希望错误中显示的更新语句尽可能不使用锁定.我不认为在这种情况下使用乐观锁定会起作用,因为乐观锁定可能会引发ActiveRecord :: StaleObjectError.
小智 8
这也是我偶然发现的一个问题.
简短的回答:这个问题没有简单的方法.所有touches都包含在同一个事务中,因此死锁.
答案很长:我猜你需要触摸对象来使某些(依赖)缓存无效.通常建议的使用touch仅适用于有限数量的"关系".例如,在更新评论时使文章无效.
我的解决方案是需要使数据库对象失效的异步集合(使用sidekiq作业).我为它编写了自己的控制逻辑,用于定义在对象更改时需要使其他对象失效的对象.例如评论==>文章.
通过这种方式,我们可以通过更冗长的方式使依赖对象无效.另外,我使用比Model.update_all"触摸链"更快的方式使其无效.它解决了我们的死锁问题(并为我们的缓存失效添加了详细程度和性能).
额外提示:不要使用updated_at.如果DB对象真的因为另一个对象发生了变化而发生变化,这是值得商榷的.覆盖cache_key模型可以轻松定义自定义缓存键"#{id}-#{valid_from}".valid_from可以是您在模型上定义的时间戳(而不是您使用的时间戳updated_at).
| 归档时间: |
|
| 查看次数: |
1848 次 |
| 最近记录: |