2009-10-08 16 views
12

मैं एक रेल एप्लिकेशन पर कुछ त्रुटियों का सामना कर रहा हूँ करने के लिए पुन: कनेक्ट करने नहीं स्थापित किया जाना की तर्ज पर के तहत:किन परिस्थितियों में आप चाहते हैं रेल, MySQL

ActiveRecord::StatementInvalid: Mysql::Error: Lost connection to MySQL server during query: SELECT * FROM `actions` WHERE (`foo`.`id` = 16) 

क्या हो रहा प्रतीत होता है कि mysql है एक टाइमआउट के बाद कनेक्शन बंद हो रहा है, और रेल देर तक नहीं देख रहे हैं जब तक कि बहुत देर हो चुकी न हो।

remedies I findappear to be database.yaml में सच करने के लिए पुनः कनेक्ट ध्वज सेट करने के लिए, या तो जैसे कुछ कोड जोड़ने किसी भी डेटाबेस कार्रवाई के लिए:

def some_database_operation 
    begin 
    Account.find(1) 
    # or some other database operations here... 
    rescue ActiveRecord::StatementInvalid 
    ActiveRecord::Base.connection.reconnect! 
    unless @already_retried 
     @already_retried = true 
     retry 
    end 
    raise 
    else 
    @already_retried = false 
    end 
end 
end 

मैं इस विकल्प over this one visible here लिस्टिंग रहा हूँ, क्योंकि इस विकल्प को जाहिरा तौर पर है लेन-देन के लिए असुरक्षित:

ActiveRecord::ConnectionAdapters::MysqlAdapter.module_eval do 
    def execute_with_retry_once(sql, name = nil) 
    retried = false 
    begin 
     execute_without_retry_once(sql, name) 
    rescue ActiveRecord::StatementInvalid => exception 
     ActiveRecord::Base.logger.info "#{exception}, retried? #{retried}" 

     # Our database connection has gone away, reconnect and retry this method 
     reconnect! 
     unless retried 
     retried = true 
     retry 
     end 
    end 
    end 

    alias_method_chain :execute, :retry_once 
end 
विकल्प इस कष्टप्रद त्रुटि से बचने के के

, YAML फ़ाइल में पुनः कनेक्ट विकल्प अब तक tidiest विकल्प द्वारा लगता है - लेकिन मैं उत्सुक हूँ; आप अपने डेटाबेस में डिफ़ॉल्ट रूप से यह मान सही क्यों नहीं सेट करेंगे?

मैं लाइन के नीचे दूसरों के भार को कम करके एक समस्या का समाधान नहीं करना चाहता हूं।

धन्यवाद,

उत्तर

12

के रूप में आप प्रश्न में बताया, एक संभव स्वचालित रूप से पुन: कनेक्ट (अगर एक प्रति बयान स्तर पर किया जाता) के पक्ष प्रभाव है कि यह लेन-देन सुरक्षित नहीं है।

MySQL documentation वास्तव में स्पष्ट रूप से कहा गया है कि ऑटो पुनः कनेक्ट सुविधा लेनदेन प्रभावित करता है:

कोई भी सक्रिय लेनदेन वापस लुढ़का कर रहे हैं और autocommit मोड रीसेट किया जाता है।

ऐसे अनुप्रयोग जो इस से निपटने के लिए लिखे गए नहीं हैं, आसानी से तोड़ सकते हैं। दस्तावेज ऑटो-रीकनेक्ट फीचर के कारण कई अन्य दुष्प्रभावों को भी सूचीबद्ध करता है, जिनमें से सभी व्यवहार को गलत तरीके से या असफल होने के लिए व्यवहार की उम्मीद करने के लिए लिखे गए नहीं हैं।

इसके अलावा, अगर डेटाबेस के लिए कनेक्शन अचानक खो दिया है, सर्वर नहीं ठीक से ताले कि कनेक्शन द्वारा आयोजित किया जा रहा था, जारी हो सकता है तो यह लगता है एक आवेदन की तरह कुछ मामलों में गतिरोध सकता है:

हैं कनेक्शन बूँदें, यह है कि सर्वर पक्ष पर कनेक्शन के साथ से संबंधित सत्र अभी भी चल रहा होगा यदि सर्वर अभी तक पता नहीं चला है कि क्लाइंट अब कनेक्ट नहीं है। इस मामले में, किसी भी मूल कनेक्शन द्वारा आयोजित ताले अभी भी, कि सत्र के हैं तो आप mysql_kill बुला द्वारा यह मारने के लिए चाहते हो सकता है()।

+2

ठीक है अब मैं पूरी तरह संदेह में हूँ। यह मुझे बताता है कि 'रीकनेक्ट' से 'सत्य' को सेट करना हानिकारक हो सकता है, क्योंकि जब लेन-देन खराब नहीं होता है तो लेन-देन वापस ले जाया जाता है। इस स्थिति से बचने के लिए सामान्य कामकाज क्या है? –

+0

समाधान यह सुनिश्चित करना है कि आपके लेन-देन "परमाणु" हैं - यानी, यदि आप कनेक्शन खो देते हैं और फिर से कनेक्ट करते हैं, तो संपूर्ण लेनदेन को फिर से लेनदेन के भीतर एक ही कथन नहीं दिया जाना चाहिए। मुझे यकीन नहीं है कि यह रेल में कैसे काम करता है, लेकिन मुझे लगता है कि एक समाधान लेनदेन को एक संग्रहीत प्रक्रिया में रखना होगा - रेल कोड में, आप संग्रहीत प्रक्रिया को चलाने के लिए एक एकल SQL कथन निष्पादित करते हैं, फिर यदि यह स्वत: पुनः कनेक्ट होता है , पूरा लेनदेन शुरुआत से शुरू होता है। –

+0

ओटीओएच, यदि आप लेनदेन का उपयोग नहीं कर रहे हैं, तो ऑटो-रीकनेक्ट सुविधा का उपयोग शायद एक समस्या से कम है। –

5

Rails 2.3 release notes (जोर मेरा) से:

4,8 पुन: कनेक्ट MySQL कनेक्शन

MySQL उसके कनेक्शन में एक पुनः कनेक्ट ध्वज का समर्थन करता है - है, तो सही पर सेट किया खोए गए कनेक्शन के मामले में छोड़ने से पहले ग्राहक सर्वर से पुनः कनेक्ट करने का प्रयास करेगा। रेलवे एप्लिकेशन से यह व्यवहार प्राप्त करने के लिए अब आप डेटाबेस.आईएमएल में अपने MySQL कनेक्शन के लिए reconnect = true सेट कर सकते हैं। डिफ़ॉल्ट गलत है, इसलिए मौजूदा अनुप्रयोगों का व्यवहार नहीं बदलता है।

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