2011-02-24 7 views
5

में एकाधिक डेटाबेस पर पुन: सक्रिय करने का सुरक्षित तरीका मेरे पास एक ही MySQL सर्वर पर चलने वाले कई रेल ऐप्स हैं। वे सभी एक ही ऐप चलाते हैं, और सभी डेटाबेस में एक ही स्कीमा होती है, लेकिन प्रत्येक डेटाबेस एक अलग ग्राहक से संबंधित होता है।रेल

वैचारिक रूप से, यहाँ मैं क्या करना चाहते हैं:

Customer.all.each do |customer| 
     connection.execute("use #{customer.database}") 
     customer.do_some_complex_stuff_with_multiple_models 
    end 

क्योंकि, जब यह एक वेब अनुरोध में चलाया जाता है, अंतर्निहित मॉडल वर्गों ए/आर कनेक्शन से अलग डेटाबेस कनेक्शन कैश यह दृष्टिकोण काम नहीं करता है पूल। तो जिस कनेक्शन पर मैं "उपयोग" कथन निष्पादित करता हूं, मॉडल का उपयोग कनेक्शन नहीं हो सकता है, इस स्थिति में यह गलत डेटाबेस से पूछताछ करता है।

ActiveRecord::Base.clear_active_connections! 
ActiveRecord::Base.establish_connection(each_customer_database_config) 

मुझे विश्वास है कि:

मैं "का उपयोग" बयान के बजाय रेल ए/आर कोड (संस्करण 3.0.3) के माध्यम से पढ़ा है, और पाश में निष्पादित करने के लिए इस कोड के साथ आया था, कनेक्शन पूल प्रति-धागा है, इसलिए ऐसा लगता है कि यह कनेक्शन पूल को पकड़ लेगा और केवल एक थ्रेड के लिए इसे फिर से स्थापित करेगा, वेब अनुरोध चालू है। लेकिन अगर कनेक्शन किसी भी तरह से साझा नहीं किया जाता है, तो मैं नहीं देख रहा हूं, मैं नहीं चाहता कि वह कोड उसी ऐप में अन्य सक्रिय वेब अनुरोधों के साथ विनाश को खत्म कर दे।

क्या यह एक चल रहे वेब ऐप में सुरक्षित है? ऐसा करने के लिए कोई और रास्ता नहीं है?

उत्तर

0

अभी आपके पास ActiveRecord में कनेक्शन प्रति कक्षा स्तर हो सकते हैं। इसकी प्रति थ्रेड आधार दिखती है क्योंकि 1.9 रूबी धागे चूसने से पहले इतनी कार्यान्वयन थ्रेड की बजाय प्रक्रिया का उपयोग कर रही थी, लेकिन यह लंबे समय तक सच नहीं हो सकती है।

लेकिन चूंकि एआर प्रति मॉडल एक थ्रेड का उपयोग करता है। आप अपने प्रत्येक डेटाबेस के लिए अलग-अलग नकली मॉडल बना सकते हैं। तो this question में दिए गए उत्तर का उपयोग करना।

कोड इस तरह कुछ दिखाई देगा। (मैंने इसका परीक्षण नहीं किया है)

Customer.all.each do |customer| 
    c_class = Class.new(ActiveRecord::Base) 
    c_class.establish_connection(each_customer_database_config) 
    c_class.table_name = customor.table_name() 
    c_class.do_something_on_diff_models_using_cutomer_from_diff_conn(customer.id) 
    c_class.clear_active_connections! 
end 
1

विभिन्न अनुरोधों के लिए एक नए डेटाबेस कनेक्शन में आईएमओ स्विचिंग एक बहुत महंगा ऑपरेशन है। एआर कनेक्शन के सीमित पूल को बनाए रखता है।

मुझे लगता है कि आपको PostgreSQL पर जाना चाहिए, जहां आपके पास स्कीमा की अवधारणा है।

एक आदर्श एसक्यूएल दुनिया में यह एक डेटाबेस

database --> schemas --> tables 

MySQL में की संरचना है, डेटाबेस और स्कीमा एक ही बात कर रहे हैं। पोस्टग्रेज़ में अलग-अलग स्कीमा हैं, जो विभिन्न ग्राहकों के लिए टेबल रख सकती हैं। आप

ActiveRecord::Base.connection.set_schema_search_path("CUSTOMER's SCHEMA") 

की स्थापना यह हालांकि हैकिंग का एक सा की आवश्यकता का विकास द्वारा एआर कनेक्शन बदले बिना मक्खी पर स्कीमा बदल सकते हैं।

+1

बस स्पष्ट करने के लिए, MySQL _does_ समर्थन एसक्यूएल स्कीमा, लेकिन मूल रूप से और infelicitously उन्हें कहा जाता है एसक्यूएल कीवर्ड "SCHEMA" संस्करण 5.0.2 (दिसंबर 2004) के बाद से मान्यता प्राप्त है। MySQL को "यूएसई फू" कहकर एक पोस्टग्रेएसक्यूएल कनेक्शन की 'search_path' को एक ही नामस्थान "foo" पर सेट करना समान है। – pilcrow

+0

बिल्कुल। आप MYSQL में "डेटाबेस एबीसी बनाने" के बजाय "स्कीमा एबीसी बनाएं" भी लिख सकते हैं। – Jagira

1

कनेक्टिंग/डिस्कनेक्ट करके डेटाबेस स्विच करना वास्तव में धीमा है, और एआर कनेक्शन पूल एक आंतरिक कैश के कारण काम नहीं करेगा। ActiveRecord::Base.table_name_prefix = "customer_" का उपयोग करने का प्रयास करें और डेटाबेस को स्थिर रखें।

0

एक ही डीबी और टेबल क्यों न रखें और अपने प्रत्येक मॉडल को ग्राहक के पास क्यों है?तो फिर तुम साथ उस ग्राहक के लिए सभी मॉडलों पा सकते हैं: "। डेटाबेस"

Customer.all.each do |customer| 
    customer.widgets 
    customer.wodgets 
    # etc 
end