ruby-on-rails - Rails 如何在不锁定的情况下触摸 Active Record 对象?

标签 ruby-on-rails caching locking associations touch

在我的照片课上,我有这个关联。

belongs_to :user, :touch => true

有一天,我得到了这个异常(exception)。
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'

我应该怎么做才能防止将来发生这样的异常?如果可能,我希望错误中显示的更新语句不使用锁定。我不认为在这种情况下使用乐观锁定会起作用,因为乐观锁定可能会引发 ActiveRecord::StaleObjectError 。

最佳答案

这也是我自己偶然发现的一个问题。

简答 : 没有简单的方法可以解决这个问题。所有 touch es 被包裹在同一个事务中,因此会出现死锁。

长答案 :我猜你需要触摸对象来使某种(依赖)缓存无效。通常推荐使用 touch仅适用于有限数量的“关系”。例如。更新评论时使文章无效。

我的解决方案是需要失效的 DB 对象的异步集合(使用 sidekiq 作业)。我为它编写了自己的控制逻辑,它定义了当对象更改时需要使哪些(其他)对象失效。例如。评论 ==> 文章。

通过这种方式,我们有一种更详细的方式使依赖对象无效。另外我使用 Model.update_all 失效了这比“触摸链”快得多。它解决了我们的死锁问题(并为我们的缓存失效增加了冗长和性能)。

额外提示:不要使用 updated_at .如果一个数据库对象真的因为另一个对象改变而改变,这是非常值得商榷的。覆盖 cache_key模型可让您轻松定义自定义缓存键,如 "#{id}-#{valid_from}" . valid_from可能是您在模型上定义的时间戳(并且您使用它来代替 updated_at )。

关于ruby-on-rails - Rails 如何在不锁定的情况下触摸 Active Record 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7587553/

相关文章:

mysql - 将包含所有数据的 MySQL 数据库从一台计算机复制到另一台计算机

ruby-on-rails - Vim:使用 rails.vim,如何让 rails.vm 使用 rspec 而不是 testunit?

ruby-on-rails - 如何在 Rails 中缓存任意对象(基于时间)?

javascript - 缓存 AJAX 请求

c# - 如何使用 Mutex 或 EventWaitHandle 同步 4 个不同的进程

c - MPI 单面 : Exclusive Lock with MPI_Win_lock_all

ruby-on-rails - 此方法如何超过 Rubocop 帐户分支条件大小?

ruby-on-rails - 保存 has_and_belongs_to_many child

scala - 同时在 Play Framework 中使用两个缓存提供程序?

locking - 强制互斥体解锁(可能来自不同的线程)?