कई घंटों के लिए ऑफ़लाइन जाने के बिना MyISAM से InnoDB तक 66,862,521 पंक्ति तालिका कैसे परिवर्तित करें?


18

क्या यह संभव है (और कैसे) ऑफ़लाइन आवेदन के बिना एक विशाल MyISAM तालिका को InnoDB में परिवर्तित करना। इसमें हर सेकंड में कुछ पंक्तियों को सम्मिलित करना होता है, लेकिन इसे लगभग 2 मिनट के लिए स्थगित करना संभव है।

स्पष्ट रूप से पहले ... इंजन = निर्दोष काम नहीं करेगा। इसके लिए मेरे पास निर्दोष इंजन के साथ एक नई तालिका बनाने और उसमें सामग्री को कॉपी करने की योजना थी। और अंत में, एप्लिकेशन लॉग थ्रेड और RENAME TABLE को सस्पेंड करें।

दुर्भाग्य से यहां तक ​​कि 100 पंक्तियों के छोटे बैचों में नकल करने से कुछ समय बाद महत्वपूर्ण अंतराल उत्पन्न होता है।

संपादित करें : मौजूदा पंक्तियों को कभी नहीं बदला जाता है, इस तालिका का उपयोग लॉगिंग के लिए किया जाता है।


1
डुप्लिकेट: dba.stackexchange.com/questions/310/…
जो

3
खैर, यह सवाल बातचीत के समय को कम करने के बारे में है। मुझे परवाह नहीं है अगर बातचीत के कुछ दिन या सप्ताह लगते हैं। लेकिन यह आवेदन के समय की आवश्यकता के बिना और ध्यान देने योग्य अंतराल बनाए बिना पृष्ठभूमि में काम करना चाहिए।
Hendrik Brummermann

जवाबों:


15

मास्टर-मास्टर सेटअप निम्नानुसार बनाएं:

  • दूसरा मास्टर बनाएं, मास्टरबी
  • MasterB गुलाम के रूप में कार्य करता है logTable
  • logTable_newनिर्दोष के रूप में बनाएँ
  • INSERT INTO logTable_new SELECT * FROM logTableMasterB पर रन (psuedocode), जो MasterA पर प्रतिकृति भेजता है
  • जब logTable_newमास्टरए सिंकिंग खत्म करता है, तो टेबल को स्वैप करें

10

की कमी को देखते हुए:

मुझे परवाह नहीं है अगर बातचीत के कुछ दिन या सप्ताह लगते हैं। लेकिन यह आवेदन के समय की आवश्यकता के बिना और ध्यान देने योग्य अंतराल बनाए बिना पृष्ठभूमि में काम करना चाहिए

जैसा कि आप लॉगिंग कर रहे हैं, अगर आपके पास मार्कर सेट करने का कोई अच्छा तरीका है, तो आप बता सकते हैं कि आप क्या प्रक्रिया शुरू करते हैं, इसलिए आप किसी भी लॉग को फिर से लागू कर सकते हैं, या लॉग को टेक्स्ट फ़ाइल में लिख सकते हैं। आप बाद में उनके साथ निगलना कर सकते हैं LOAD DATA INFILE

समस्या का एक हिस्सा यह है कि छोटे बैचों में लिखने का मतलब है कि अनुक्रमित को बार-बार पुन: विवादित करना पड़ता है; आप इसे एक साथ चलाने से बेहतर हैं, लेकिन यह सिस्टम पर कुछ 'ध्यान देने योग्य' अंतराल का कारण हो सकता है .. लेकिन आपको इसे अपने उत्पादन सर्वर पर नहीं करना होगा।

  1. लॉगिंग को रोकें या कुछ मार्कर सेट करें ताकि आप बाद में इस बिंदु से लॉग को फिर से लागू कर सकें।
  2. अपने MyISM टेबल को दूसरे सिस्टम में कॉपी करें
  3. अन्य प्रणाली पर, एक अलग नाम के तहत एक InnoDB तालिका बनाएं और डेटा को माइग्रेट करें (यह इसे डंप करने और उपयोग करने के लिए तेज़ भी हो सकता है LOAD DATA INFILE)
  4. मूल प्रणाली में वापस InnoDB तालिका की प्रतिलिपि बनाएँ
  5. लॉगिंग के लिए एक और मार्कर सेट करें।
  6. पिछले दो मार्करों के बीच से नई तालिका में लॉग के सभी पुन: लागू करें।
  7. (चरण 5 और 6 को दोहराएं यदि चरण # 6 में एक मिनट से अधिक समय लगा, तो ऐसे समय तक जब तक कि यह केवल कुछ सेकंड हो)
  8. तालिकाओं की अदला-बदली करें (पुराने नाम को table_BACKUP में बदलें, पुराने के नाम से नया एक)
  9. पिछले मार्कर से लॉग को पकड़ें।

9

दुर्भाग्य से यहां तक ​​कि 100 पंक्तियों के छोटे बैचों में नकल करने से कुछ समय बाद महत्वपूर्ण अंतराल उत्पन्न होता है।

क्या आप प्रत्येक बैच के बीच कोई देरी जोड़ रहे हैं, या सिर्फ अपडेट्स को बैचने और प्रत्येक बैच को सीधे पिछले एक के बाद चला रहे हैं?

यदि ऐसा है तो अपनी पसंदीदा भाषा में रूपांतरण को स्क्रिप्ट के साथ कुछ इस तरह आज़माएँ:

repeat
    copy oldest 100 rows that haven't been copied yet to new table
    sleep for as long as that update took
until there are <100 rows unprocessed
stop logging service
move the last few rows
rename tables
restart logging
delete the old table when you are sure the conversion has worked

यह सुनिश्चित करना चाहिए कि रूपांतरण आपके सर्वर की क्षमता से अधिक या कम-आधे से अधिक नहीं लेता है, यहां तक ​​कि लोड के अंतर के लिए भी अनुमति देता है क्योंकि सिस्टम का उपयोग समय के साथ बदलता रहता है।

या यदि आप जितना संभव हो उतने समय का उपयोग करना चाहते हैं जब सेवा अपेक्षाकृत निष्क्रिय है, लेकिन डेटाबेस से अपने उपयोगकर्ताओं के लिए कुछ काम करने की आवश्यकता होने पर, बैक ऑफ (संभावित रूप से काफी समय तक रुकने) की जगह ले लेता sleep for as long as the update tookहै if the server's load is above <upper measure>, sleep for some seconds then check again, loop around the sleep/check until the load drops below <lower measure>। इसका मतलब यह है कि यह शांत समय में आगे भाप सकता है, लेकिन सर्वर पूरी तरह से काम करने में व्यस्त होने पर इसे पूरी तरह से रोक देगा। लोडिंग का निर्धारण आपके OS पर निर्भर करेगा - Linux के तहत और इसी तरह के 1-मिनट लोड औसत मूल्य से /proc/loadavgया आउटपुट को uptimeकरना चाहिए। <lower measure>और <upper measure>इसका एक ही मूल्य हो सकता है, हालांकि यह सामान्य रूप से नियंत्रण में होता है जैसे कि इसमें अंतर होता है इसलिए आपकी प्रक्रिया शुरू नहीं होती है क्योंकि लोड माप पर प्रभाव होने के कारण इसे फिर से शुरू कर दिया जाता है।

बेशक यह उन तालिकाओं के लिए काम नहीं करेगा जहां पुरानी पंक्तियों को संशोधित किया जा सकता है, लेकिन आपके द्वारा वर्णित एक लॉग टेबल के लिए ठीक काम करेगा।

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


4

क्या यह काम पसंद आएगा?

  1. लॉगिंग रोकें (ताकि $auto_incrementआपकी लॉगिंग टेबल mytable बदल न जाए)।
  2. $auto_incrementमूल्य का उपयोग कर ध्यान दें SHOW TABLE STATUS LIKE 'mytable'
  3. CREATE TABLE mytable_new LIKE mytable
  4. ALTER TABLE mytable_new AUTO_INCREMENT=$auto_increment ENGINE=Innodb
  5. RENAME TABLE mytable TO mytable_old, mytable_new TO mytable
  6. फिर से लॉगिंग सक्षम करें। इनोडब टेबल अब आबाद होने लगेगी।
  7. INSERT INTO mytable SELECT * FROM mytable_old

आप चरण 7 बैचों में या एक बयान में कर सकते हैं क्योंकि यह सामान्य लॉगिंग के लिए अवरुद्ध नहीं होना चाहिए।


यह अभी भी अवरुद्ध हो जाएगा, क्योंकि जिस तरह से innodb auto_increment को संभालता है,। डिफ़ॉल्ट रूप से इन्सोडब एक auto_increment कॉलम में डालने पर एक टेबल लेवल लॉक लेता है, और इन्सर्ट समाप्त होते ही लॉक को रिलीज़ करता है।
ovais.tariq
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.