2011-09-28 17 views
11

मेरी फोटो कक्षा में मेरे पास यह सहयोग है।रेल लॉक किए बिना सक्रिय रिकॉर्ड ऑब्जेक्ट को कैसे स्पर्श करें?

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 es उसी लेनदेन में लिपटे हैं, इसलिए डेडलॉक।

लंबे उत्तर: मुझे लगता है कि आपको कुछ प्रकार (आश्रित) कैश को अमान्य करने के लिए स्पर्श ऑब्जेक्ट की आवश्यकता है। आमतौर पर touch का अनुशंसित उपयोग केवल "रिश्तों" की सीमित मात्रा के लिए काम करता है। जैसे जब टिप्पणी अपडेट की जा रही है तो आलेख को अमान्य कर दें।

मेरा समाधान डीबी ऑब्जेक्ट्स के एसिंक्रोनस संग्रह (साइडकीक जॉब का उपयोग करके) को अमान्य करने की आवश्यकता है। मैंने इसके लिए अपना खुद का नियंत्रण तर्क लिखा है जो परिभाषित करता है कि किसी ऑब्जेक्ट को बदलने पर (अन्य) ऑब्जेक्ट्स को अमान्य करने की आवश्यकता होती है। जैसे टिप्पणी ==> लेख।

इस तरह हमारे पास निर्भर वस्तुओं को अमान्य करने का एक और तरीका था। इसके अलावा मैंने Model.update_all का उपयोग करके अमान्य कर दिया जो "स्पर्श श्रृंखला" के बाद तेज़ी से था। इसने हमारी डेडलॉक समस्याओं को हल किया (और हमारे कैश अमान्यता में वर्बोजिटी और प्रदर्शन जोड़ा)।

अतिरिक्त युक्ति: updated_at का उपयोग न करें। यदि डीबी ऑब्जेक्ट वास्तव में बदल गया है तो यह बहुत बहस योग्य है क्योंकि एक और वस्तु बदल गई है। 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 में भी जोड़ना होगा, उदाहरण के लिए [वर्ग]/[id] - [timestamp] http://signalvnoise.com/posts/3113- कैसे-कुंजी आधारित-संचय-समाप्ति-काम करता है – iheggie

संबंधित मुद्दे