2011-09-28 4 views
11

내 사진 수업에는이 연관성이 있습니다.잠금없이 Active Record Object를 터치하는 방법은 무엇입니까?

belongs_to :user, :touch => true 

어느 날이 예외가 발생했습니다.

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를 발생시킬 것이기 때문에 낙관적 인 잠금을 사용하는 것이이 경우에는 작동하지 않을 것이라고 생각합니다.

답변

8

나는 그것이 나 자신에게도 걸린 문제 다.

짧은 대답 :이 문제를 해결하는 쉬운 방법은 없습니다. touch은 모두 동일한 트랜잭션으로 래핑되므로 교착 상태가 발생합니다.

긴 대답 : 일종의 (종속) 캐시를 무효화하려면 터치 객체가 필요합니다. 일반적으로 touch의 권장 사용은 제한된 "관계"에 대해서만 작동합니다. 예 : 댓글이 업데이트 될 때 기사를 무효화합니다.

내 솔루션은 무효화해야하는 DB 개체의 비동기 수집 (sidekiq 작업 사용)입니다. 객체를 변경했을 때 (다른) 객체를 무효화해야한다고 정의하는 자체 제어 로직을 작성했습니다. 예 : 의견 ==> 기사.

이렇게하면 종속 객체를 무효화하는 방법이 더 길어졌습니다. 플러스 나는 Model.update_all을 사용하는 것을 무효화했습니다. 그 방법은 "터치 체인"이었습니다. 교착 상태 문제를 해결하고 캐시 무효화에 자세한 정보와 성능을 추가했습니다.

추가 팁 : updated_at을 사용하지 마십시오. 다른 객체가 변경되어 DB 객체가 실제로 변경된 경우 매우 논쟁의 여지가 있습니다. cache_key 모델을 덮어 쓰면 "#{id}-#{valid_from}"과 같은 맞춤 캐시 키를 쉽게 정의 할 수 있습니다. valid_from은 모델에 정의한 타임 스탬프 (updated_at 대신에 사용하는 타임 스탬프) 일 수 있습니다.

+0

답변 해 주셔서 감사합니다. 2 년이 지난 지금 왜 내가 터치를 사용하는지 잘 모르겠습니다. 캐시를 무효화하는 것이 좋은 이유 인 것 같습니다. 이제 스위퍼를 사용하여 캐시 항목을 만료시킵니다. http://guides.rubyonrails.org/caching_with_rails.html#sweepers. 나는 더 이상 아무데도 터치를 사용하지 않습니다. –

+0

나는 valid_from에 대한 아이디어가 마음에 들지만, 클래스 이름을 cache_key에도 추가 할 필요가 있다고 생각합니다. 예를 들어 [class]/[id] - [timestamp] http://signalvnoise.com/posts/3113- 키 기반의 캐시 만료 - 작동 방식 – iheggie

관련 문제