mysql थ्रॉटल वैकल्पिक टैब डिस्क उपयोग




database indexing (3)

  1. real तालिका के समान एक new तालिका बनाएं, लेकिन संशोधित अनुक्रमणिका के साथ। एक PRIMARY KEY शामिल करें ताकि आप फिर से फंस पाए न जाए। - यह ALTER , लेकिन अभी तक "पॉप्युलेट" नहीं है
  2. नई तालिका में, पुरानी सामग्री के लिए त्रैमासिक या वार्षिक विभाजन का उपयोग करें; वर्तमान और (बाद में) भविष्य के विभाजन के लिए मासिक। - यह कुल विभाजनों की संख्या को नीचे रखना है अंगूठे का मेरा नियम "50 से अधिक विभाजन नहीं है" (मुझे बताएं अगर आपको इस योजना में कोई समस्या है।)
  3. धीरे-धीरे पुराने डेटा से सभी डेटा को new तालिका में कॉपी करने के लिए एक स्क्रिप्ट लिखें। चंकिंग पर मेरी सलाह यहां उपयोगी हो सकती है।
  4. आपके पकड़े जाने से पहले, एक नया विभाजन बनाएँ लेकिन अभी तक इसकी प्रतिलिपि नहीं करें पिछले विभाजन के अंत में "प्रतिलिपि" स्क्रिप्ट को रोकें।
  5. जब इस नए विभाजन को छोड़कर पकड़ा गया, लिखना बंद करो
  6. अंतिम विभाजन की प्रतिलिपि बनाएँ - जहां चरण # 4 बंद का भुगतान करता है
  7. परमाणु स्वैप: RENAME TABLE real TO old, new TO real; । और फिर से लिखना चालू करें।

सभी लिपियों को लिखना और अन्य मशीनों पर अभ्यास करना जोरदार सलाह दी जाती है। यह प्रथा कुल के एक छोटे उपसमूह पर हो सकती है, लेकिन इसमें कम से कम कुछ विभाजन होना चाहिए।

मैं MySQL ऑनलाइन डीडीएल सीमाएं पृष्ठ से कुछ के साथ शुरू करूँगा:

ऑनलाइन डीडीएल ऑपरेशन को रोकने या ऑनलाइन डीडीएल ऑपरेशन के लिए I / O या CPU उपयोग को थ्रॉटल करने के लिए कोई तंत्र नहीं है।

हालांकि, मैं अभी भी ऐसे समाधानों में दिलचस्पी लेता हूं जिनकी मुझे याद हो सकती थी

स्थिति: सूचकांक बड़ा और बड़ा हो रहे हैं, और वे इतना बड़ा हो रहे हैं कि उपयोग किए जाने वाले प्रश्नों के लिए पर्याप्त मेमोरी नहीं होगी, डिस्क आई / ओ को बढ़ना होगा, और सब कुछ ख़ास अराजकता में उतर जाएगा। नई संमिश्र इंडेक्स बनाये गये हैं जो छोटे होते हैं, लेकिन समस्या कुछ भी तोड़ने के बिना ALTER TABLE चल रही है

तथ्य निम्नानुसार हैं:

  1. यह एक InnoDB तालिका है
  2. तालिका में कोई प्राथमिक कुंजी या अद्वितीय अनुक्रमणिका नहीं है।
  3. कॉलम का कोई संयोजन प्राथमिक कुंजी या अद्वितीय अनुक्रमणिका के रूप में उपयुक्त नहीं है।
  4. तालिका में कोई विदेशी कुंजी नहीं है
  5. मेज प्रति माह विभाजन (वर्तमान में 50) है
  6. तालिका को हर समय लिखना स्वीकार करना चाहिए
  7. नवीनतम 3-6 विभाजन को पढ़ना अवश्य स्वीकार करना चाहिए।
  8. एक id कॉलम है, लेकिन यह अद्वितीय नहीं है
  9. तालिका में लगभग 2 अरब पंक्तियाँ हैं।
  10. वर्तमान महीने का विभाजन केवल एक है जो लिखता है।
  11. विभाजन 1 महीने पहले किया जाता है; वहाँ हमेशा एक खाली विभाजन है

SHOW CREATE TABLE (मैं सभी विभाजन शामिल नहीं था):

CREATE TABLE `my_wonky_table` (
  `id` bigint(20) unsigned NOT NULL,
  `login` varchar(127) DEFAULT NULL,
  `timestamp` int(10) unsigned NOT NULL,
  `ip` varchar(32) CHARACTER SET ascii DEFAULT NULL,
  `val_1` int(10) unsigned DEFAULT NULL,
  `val_2` varchar(127) DEFAULT NULL,
  `val_3` varchar(255) DEFAULT NULL,
  `val_4` varchar(127) DEFAULT NULL,
  `val_5` int(10) unsigned DEFAULT NULL,
  KEY `my_wonky_table_id_idx` (`id`),
  KEY `my_wonky_table_timestamp_idx` (`timestamp`),
  KEY `my_wonky_table_val_1_idx` (`val_1`,`id`),
  KEY `my_wonky_table_val_2_idx` (`val_2`,`id`),
  KEY `my_wonky_table_val_4_idx` (`val_4`,`id`),
  KEY `my_wonky_table_val_5_idx` (`val_5`,`id`),
  KEY `my_wonky_table_ip_idx` (`ip`,`id`),
  KEY `my_wonky_table_login_idx` (`login`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (`id`)
(PARTITION pdefault VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */

क्वेरी के बारे में: यह हमेशा id पर एक SELECT होता है, और बाकी सब कुछ फ़िल्टर करने के लिए उपयोग किया जाता है

मैं क्या बचाना चाहूंगा:

  • डेटाबेस इंस्टेंस को बंद करना
  • 100% डिस्क आई / ओ

मैंने pt-online-schema-change उपकरण का उपयोग करने के बारे में सोचा था, लेकिन कोई प्राथमिक कुंजी दीवार नहीं चला एक अलग समाधान कोड में ऐसा करने के लिए होगा, ट्रिगर्स को कोड बेस में प्रभावी ढंग से आगे बढ़ाना होगा, और धीरे-धीरे कुछ अजीब विखंडू (जैसे टाइमस्टैम्प कॉलम का उपयोग करते हुए एक घंटे के मूल्य के आंकड़ों के भाग) का उपयोग करके डेटा को कॉपी कर देगा क्योंकि कोई अनूठी अनुक्रमणिका नहीं है

क्या अन्य समाधान और / या उपकरण उपलब्ध हैं?


मैं इसे एक अलग जवाब के रूप में प्रस्तुत करता हूं, क्योंकि अंतरतम भाग पूरी तरह से अलग है।

मेरे दूसरे उत्तर के साथ, आपको new सारणी के साथ नई तालिका की आवश्यकता है, साथ ही सभी डेटा को कॉपी करने के लिए एक स्क्रिप्ट की आवश्यकता है। हालांकि, मांस आपके आवेदन में ट्रिगर को अनुकरण करना है।

सौभाग्य से, आपके पास id , हालांकि यह PRIMARY KEY नहीं है और, भले ही यह UNIQUE नहीं है, इसका इस्तेमाल किया जा सकता है (संभालने में आपके पास एक ही आईडी के साथ हजारों पंक्तियां नहीं हैं - यदि आप करते हैं, तो हम आगे बात कर सकते हैं)।

"कॉपी स्क्रिप्ट" और एप्लिकेशन एक-दूसरे से बात करते हैं

कॉपी स्क्रिप्ट लूप लूप में है:

  • SELECT GET_LOCK('copy', 5), high_water_mark FROM tbl; - (या कुछ अन्य समयबाह्य)
  • id BETWEEN high_water_mark AND high_water_mark + 999 साथ पंक्तियों की प्रतिलिपि करें id BETWEEN high_water_mark AND high_water_mark + 999
  • UPDATE tbl SET high_water_mark = high_water_mark + 1000;
  • संक्षेप में रोकें (1 सेकंड?)
  • लूप तक कोई और ids

आवेदन, पढ़ने के दौरान, पुराने तालिका से पढ़ना जारी रहता है। लेकिन लिखते समय, यह करता है:

  • SELECT GET_LOCK('copy', 5), high_water_mark FROM tbl; - (या कुछ अन्य समयबाह्य)
  • यदि समय समाप्त हो गया है, तो कुछ फिक्सिंग की आवश्यकता है
  • पुराने तालिका में लिखें - (इसलिए, काम जारी रखने के लिए पढ़ता है)
  • यदि id <= high_water_mark , नई तालिका के लिए भी लिखें।
  • SELECT RELEASE_LOCK('copy');

प्रगति की निगरानी करें कुछ बिंदु पर, आपको सब कुछ रोकना होगा, पिछले कुछ पंक्तियों की प्रतिलिपि बनाएँ और RENAME TABLE

मैं समय समाप्त, नींद, या आकार का आकार के लिए आपके इष्टतम मूल्यों को नहीं जानता। लेकिन मुझे नहीं लगता कि चक का आकार 1K से बड़ा होना चाहिए।

इस तकनीक में आपको कई तरह के बदलावों के लिए लाभ हैं, जिनकी आपको भविष्य में आवश्यकता हो सकती है, इसलिए जगह में हिम्मत रखें।


यह आपके द्वारा उपयोग किए जा रहे MySQL संस्करण और संस्करण के नीचे आ रहा है, लेकिन यदि यह एक थ्रेड प्रति कनेक्शन है (my.cnf thread_handling=one-thread-per-connection , जो आपके बिल्ड पर डिफ़ॉल्ट हो सकता है), और आप एक नया कनेक्शन में आपका renice वर्कलोड, फिर वर्कलोड एक अद्वितीय पीआईडी ​​है, और आप renice पर ionice / renice उपयोग कर सकते हैं।

मेरे पास कुछ गड़बड़ जवाब है, लेकिन यह अन्य विकल्पों की तुलना में कम आक्रामक है

यदि आप ps -eLf |grep mysql को देखते हैं तो आप थ्रेड / लाइटवेट प्रक्रियाओं को देख सकते हैं, और यह समझने की आवश्यकता है कि आपके विशिष्ट कनेक्शन के साथ पीआईडी ​​क्या है। यदि आप टीसीपी के माध्यम से जुड़ते हैं, तो आप अपने स्थानीय कनेक्शन पोर्ट से मिलान कर सकते हैं और मानचित्र को विशिष्ट थ्रेड को खोजने के लिए एलएसओफ़ ​​के खिलाफ कर सकते हैं। अन्य तरीकों से संभव है w / strace, systemtap और अधिक, या आप के लिए देख सकते हैं एक प्रारंभिक क्वेरी चल रहा है।

उसके बाद, आप सिस्टम पर पीआईडी ​​को प्रभावित करने के लिए ionice / renice का उपयोग कर सकते हैं। आप वास्तव में यह सुनिश्चित करना चाहते हैं कि आप पीआईडी ​​को कैद कर लें, और बाद में अच्छा और प्राथमिकता स्तर को रीसेट करें, और कुछ भी प्रभावित न करें

अन्य लोगों के साथ, आपको वास्तव में इस तालिका को दीर्घकालिक में नयी आकृति प्रदान करने की आवश्यकता है। विभाजन उपयोगी है, लेकिन एंडगैम नहीं है, क्योंकि आप ऑनलाइन डाटा के 1.3 टीआईबी चला रहे हैं, और आप बताते हैं कि आपको केवल हाल के 3-6 विभाजनों से पढ़ने की जरूरत है। मूल विभाजनों को जोड़ने से पहले MySQL से आ रहा है, मुझे लगता है कि यह VIEW और अलग तालिकाओं के लिए एक अच्छा मामला होगा (जब आपको रोलओवर की आवश्यकता होती है तो एटम को अपडेट करें)। यह आपको ऑफ़लाइन संग्रहण के लिए कुछ पुराने तालिकाओं को तुच्छ रूप से स्थानांतरित करने देगा





alter-table