टेबल लॉकिंग के बिना एक विशाल MySQL उत्पादन तालिका पर एक इंडेक्स बनाएं


104

मुझे ~ 5M पंक्तियों MySQL टेबल पर एक इंडेक्स बनाने की आवश्यकता है। यह एक उत्पादन तालिका है, और अगर मैं एक CREATE INDEX स्टेटमेंट चलाता हूं, तो मुझे हर चीज का एक पूरा ब्लॉक होने का डर है ...

वहाँ आवेषण और चयन को अवरुद्ध किए बिना उस सूचकांक को बनाने का एक तरीका है?

बस सोच रहा था कि मुझे रोकना नहीं है, सूचकांक बनाएं और अपने सिस्टम को पुनरारंभ करें!


1
सुनिश्चित करें कि आपके myisam_sort_buffer_size और myisam_max_sort_file_size काफी बड़े हैं।
जॉन ब्लैक

जवाबों:


130

[२०१ My] अपडेट: MySQL 5.6 में ऑनलाइन इंडेक्स अपडेट के लिए समर्थन है

https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html#online-ddl-index-syntax-notes

MySQL 5.6 और उच्चतर में, तालिका पढ़ने और लिखने के लिए उपलब्ध रहती है जबकि सूचकांक बनाया या गिराया जा रहा है। CREATE INDEX या DROP INDEX स्टेटमेंट केवल उन सभी लेन-देन के बाद खत्म होता है जो टेबल तक पहुंच रहे हैं, पूरे हो गए हैं, ताकि इंडेक्स की प्रारंभिक स्थिति तालिका की सबसे हाल की सामग्री को दर्शाए। पहले, तालिका को संशोधित करते समय एक इंडेक्स बनाया या गिराया जाता है, जिसके परिणामस्वरूप तालिका में INSERT, UPDATE, या DELETE कथन को रद्द करने वाला गतिरोध उत्पन्न होता है।

[२०१५] अपडेटिंग टेबल इंगित करता है कि ब्लॉक MySQL 5.5 में लिखते हैं

उपरोक्त उत्तर से:

"यदि डेटाबेस के ऑनलाइन होने के दौरान 5.1 से अधिक सूचकांकों का उपयोग करने पर आपका निर्माण होता है। तो चिंता न करें कि आप उत्पादन प्रणाली के उपयोग को बाधित नहीं करेंगे।"

यह **** FALSE **** है (कम से कम MyISAM / InnoDB तालिकाओं के लिए, जो कि वहां के 99.999% लोग उपयोग करते हैं। क्लस्टर संस्करण अलग है।)

एक मेज पर अद्यतन संचालन कर रहा होगा ब्लॉक , जबकि सूचकांक बनाया जा रहा है। MySQL वास्तव में, वास्तव में इस बारे में बेवकूफ है (और कुछ अन्य चीजें)।

टेस्ट स्क्रिप्ट:

(   
  for n in {1..50}; do
    #(time mysql -uroot -e 'select  * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
    (time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
  done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'

मेरा सर्वर (InnoDB):

Server version: 5.5.25a Source distribution

आउटपुट (नोटिस कैसे 6 वें ऑपरेशन ब्लॉक ~ 400ms के लिए यह सूचकांक अद्यतन खत्म करने के लिए लेता है):

 1  real    0m0.009s
 2  real    0m0.009s
 3  real    0m0.009s
 4  real    0m0.012s
 5  real    0m0.009s
Index Update - START
Index Update - FINISH
 6  real    0m0.388s
 7  real    0m0.009s
 8  real    0m0.009s
 9  real    0m0.009s
10  real    0m0.009s
11  real    0m0.009s

बनाम पढ़े गए ऑपरेशन जो ब्लॉक नहीं होते (स्क्रिप्ट में लाइन टिप्पणी स्वैप करें):

 1  real    0m0.010s
 2  real    0m0.009s
 3  real    0m0.009s
 4  real    0m0.010s
 5  real    0m0.009s
Index Update - START
 6  real    0m0.010s
 7  real    0m0.010s
 8  real    0m0.011s
 9  real    0m0.010s
...
41  real    0m0.009s
42  real    0m0.010s
43  real    0m0.009s
Index Update - FINISH
44  real    0m0.012s
45  real    0m0.009s
46  real    0m0.009s
47  real    0m0.010s
48  real    0m0.009s

डाउनटाइम के बिना MySQL के स्कीमा को अपडेट करना

इस प्रकार, MySql स्कीमा को अपडेट करने के लिए केवल एक ही तरीका है जो मुझे पता है और एक उपलब्धता आउटेज से पीड़ित नहीं है। परिपत्र स्वामी:

  • मास्टर A में आपका MySQL डेटाबेस चल रहा है
  • मास्टर बी को सेवा में लाओ और यह मास्टर ए से लिखता है (बी ए का गुलाम है)
  • मास्टर बी पर स्कीमा अपडेट करें। यह अपग्रेड के दौरान पीछे आ जाएगा
  • मास्टर बी को पकड़ने दो। अपरिवर्तनीय: आपका स्कीमा परिवर्तन आवश्यक रूप से डाउनग्रेड स्कीमा से दोहराए गए आदेशों को संसाधित करने में सक्षम होना चाहिए। अनुक्रमण परिवर्तन योग्य हैं। साधारण स्तंभ परिवर्धन आमतौर पर योग्य होते हैं। कोई कॉलम निकाल रहा है? शायद ऩही।
  • मुख्य रूप से मास्टर ए से मास्टर बी तक सभी ग्राहक स्वैप करते हैं। यदि आप सुरक्षित रहना चाहते हैं (मुझ पर विश्वास करें, आप करते हैं), तो आपको यह सुनिश्चित करना चाहिए कि ए को अंतिम लिखना बी BEORE को दोहराया जाए।B अपना पहला लेखन लेता है। यदि आप समवर्ती लेखन को 2+ मास्टर्स की अनुमति देते हैं, तो ... आप DEEP स्तर पर MySQL प्रतिकृति को बेहतर ढंग से समझते हैं या आप दर्द की दुनिया के लिए नेतृत्व कर रहे हैं। अत्यधिक दर्द। जैसे, क्या आपके पास एक कॉलम है जो AUTOINCREMENT है ??? आप खराब हैं (जब तक कि आप एक मास्टर पर नंबर का उपयोग नहीं करते हैं और दूसरे पर ऑड्स)। "सही काम करने के लिए" MySQL प्रतिकृति पर भरोसा न करें। यह स्मार्ट नहीं है और आपको बचाएगा नहीं। यह कमांड लाइन से द्विआधारी लेनदेन लॉग की प्रतिलिपि बनाने और हाथ से उन्हें फिर से देखने की तुलना में बस थोड़ा कम सुरक्षित है। फिर भी, पुराने मास्टर से सभी ग्राहकों को डिस्कनेक्ट करना और उन्हें नए मास्टर को फ़्लिप करना सेकंड के एक मामले में किया जा सकता है, बहु-घंटे स्कीमा उन्नयन के लिए इंतजार करने की तुलना में बहुत तेजी से।
  • अब मास्टर बी आपका नया मास्टर है। आपके पास नया स्कीमा है। ज़िंदगी अच्छी है। एक बियर; सबसे खराब है।
  • मास्टर ए के साथ प्रक्रिया को दोहराएं, अपने स्कीमा को अपग्रेड करें ताकि वह आपका नया माध्यमिक मास्टर बन जाए, इस घटना को संभालने के लिए तैयार कि आपका प्राथमिक मास्टर (मास्टर बी) अब शक्ति खो देता है या बस आप पर मर जाता है।

स्कीमा को अपडेट करने का एक आसान तरीका यह नहीं है। एक गंभीर उत्पादन वातावरण में व्यावहारिक; हाँ यही है। कृपया, कृपया, कृपया, अगर कोई अवरोधन के बिना MySQL तालिका में एक सूचकांक जोड़ने का एक आसान तरीका है, तो मुझे बताएं।

Googling मुझे इस लेख की ओर ले जाती है जो एक समान तकनीक का वर्णन करता है। इससे भी बेहतर, वे कार्यवाही में उसी बिंदु पर पीने की सलाह देते हैं (ध्यान दें कि मैंने लेख पढ़ने से पहले अपना जवाब लिखा था)!

पर्कोना का पीटी-ऑनलाइन-स्कीमा-परिवर्तन

लेख मैं एक उपकरण के बारे में बात करती है ऊपर लिंक, pt-ऑनलाइन-स्कीमा परिवर्तन , इस प्रकार है कि काम करता है:

  • मूल के समान संरचना के साथ नई तालिका बनाएं।
  • नए टेबल पर स्कीमा अपडेट करें।
  • मूल तालिका पर एक ट्रिगर जोड़ें ताकि परिवर्तनों को कॉपी के साथ सिंक में रखा जाए
  • मूल तालिका से बैचों में पंक्तियों की प्रतिलिपि बनाएँ।
  • मूल तालिका को रास्ते से हटाएं और नई तालिका से प्रतिस्थापित करें।
  • पुराना टेबल गिरा दो।

मैंने कभी भी उपकरण को स्वयं आज़माया नहीं है। YMMV

आरडीएस

मैं वर्तमान में Amazon के RDS के माध्यम से MySQL का उपयोग कर रहा हूं । यह वास्तव में एक निफ्टी सेवा है जो लपेटता है और MySQL का प्रबंधन करता है, जिससे आप एक ही बटन के साथ नई रीड प्रतिकृतियां जोड़ सकते हैं और हार्डवेयर SKU में डेटाबेस को पारदर्शी रूप से अपग्रेड कर सकते हैं। यह वास्तव में सुविधाजनक है। आपको डेटाबेस तक सुपर एक्सेस नहीं मिलती है, इसलिए आप सीधे प्रतिकृति के साथ पेंच नहीं कर सकते हैं (यह एक आशीर्वाद या अभिशाप है)। हालाँकि, आप अपने स्कीमा परिवर्तन को केवल-पढ़ने के लिए गुलाम बनाने के लिए रीड रेप्लिका प्रोमोशन का उपयोग कर सकते हैं , फिर उस दास को बढ़ावा देकर अपने नए मास्टर बन सकते हैं। बिल्कुल वैसा ही टोटका जैसा कि मैंने ऊपर वर्णित किया है, बस अमल करना बहुत आसान है। वे अभी भी कट-ओवर के साथ आपकी मदद करने के लिए बहुत कुछ नहीं करते हैं। आपको अपने ऐप को फिर से कॉन्फ़िगर और पुनरारंभ करना होगा।


3
मास्टर-स्लेव प्रतिकृति में भी पीटी-ऑनलाइन-स्कीमा-परिवर्तन महान काम करता है। मैंने इसका उपयोग हमारे माइग्रेशन मास्टर db पर व्यस्त रीड 20M + रिकॉर्ड टेबल पर 2 प्रतिकृति दासों के साथ बिना किसी हिचकी या डाउनटाइम के लाइव प्रवास करने के लिए किया है। स्क्रिप्ट तैयार करने में कुछ समय लगता है, और मुझे आमतौर पर कच्चे SQL परिवर्तन और .sh फ़ाइल को रैपर के रूप में बनाने के लिए एक ही SQL बनाने के लिए होता है, लेकिन एक ही SQL चलाने के लिए लेकिन टुकड़ा प्रारूप (कोई भिन्न नहीं)। आप पीटी-ऑनलाइन-स्कीमा-परिवर्तन के साथ कई कमांड चला सकते हैं, उन्हें स्ट्रिंग करके और अल्पविराम द्वारा अलग किया जा सकता है।
एलेक्स ले

-1; मुझे पुराने संस्करणों के बारे में जानकारी नहीं है, लेकिन मुझे पता है कि सूचकांक निर्माण MySQL 5.6+ में समवर्ती DML को ब्लॉक नहीं करता है (जिसके लिए एक RC उस समय मौजूद था जब यह उत्तर लिखा गया था, और जिसे आधिकारिक रूप से जारी किया गया था जब यह उत्तर दिया गया था मई 2013 में संपादित किया गया) क्योंकि मैंने अभी भी आवेषण को स्वीकार करते हुए उत्पादन तालिकाओं पर बहु-घंटे सूचकांक बनाने के लिए इस पर भरोसा किया है। जब आप 5.5 और उससे नीचे के डीएमएल को इंडेक्स क्रिएट करने के बारे में सही हो सकते हैं, तो यहां प्रदर्शित उप-सेकंड देरी पूरी तरह से आश्वस्त नहीं है।
मार्क अमेरी

@ मकर्मी - अवरुद्ध व्यवहार व्यवहार को रोक रहा है, और 400ms एक अनंत काल है। इंडेक्स अपडेट के लिए MySQL 5.5 ब्लॉक। एक बड़ा परीक्षण डेटाबेस बनाएँ, और यह सेकंड, घंटे या दिनों के लिए ब्लॉक हो जाएगा। मैंने इस पोस्ट को MySQL 5.6 से पहले ऑनलाइन स्कीमा अपडेट किया था, इसलिए मेरी मूल सामग्री उस तथ्य को प्रतिबिंबित नहीं करती है। मैंने नई उपलब्ध जानकारी को दर्शाने के लिए पोस्ट को अपडेट किया है।
डेव डॉपसन

@DaveDopson, क्या आप 100% सुनिश्चित हैं कि केवल UPDATE ऑपरेशन अवरुद्ध हैं?
toto_tico

मेरे द्वारा परीक्षण किए गए संस्करण के लिए यह मामला था।
डेव डॉपसन

67

जैसा कि यह ब्लॉग पोस्ट करता है, ALTER TABLEMySQL 5.6 के लिए InnoDB तंत्र को पूरी तरह से नया रूप दिया गया है।

(इस विषय के एक विशेष अवलोकन के लिए, MySQL प्रलेखन दोपहर की रीडिंग के लायक प्रदान कर सकता है।)

/ के परिणामस्वरूप लॉक के बिना एक तालिका में एक सूचकांक जोड़ने के लिए , निम्नलिखित कथन प्रारूप का उपयोग किया जा सकता है:UPDATEINSERT

ALTER TABLE my_table ADD INDEX my_table__idx (my_column), ALGORITHM=INPLACE, LOCK=NONE;


16

MySQL 5.6 अपडेट (फ़ेब 2013): अब आप पढ़े और लिख सकते हैं और संचालन कर सकते हैं जबकि एक इंडेक्स भी बनाया जा रहा है जिसमें InnoDB टेबल भी शामिल है - http://dev.mysql.com/doc/refman/5.6/en/innodb-create.index -overview.html

MySQL 5.6 और उच्चतर में, तालिका पढ़ने और लिखने के लिए उपलब्ध रहती है जबकि सूचकांक बनाया या गिराया जा रहा है। CREATE INDEX या DROP INDEX स्टेटमेंट केवल उन सभी लेन-देन के बाद खत्म होता है जो टेबल तक पहुंच रहे हैं, पूरे हो गए हैं, ताकि इंडेक्स की प्रारंभिक स्थिति तालिका की सबसे हाल की सामग्री को दर्शाए। पहले, तालिका को संशोधित करते समय एक इंडेक्स बनाया या गिराया जाता है, जिसके परिणामस्वरूप तालिका में INSERT, UPDATE, या DELETE कथन को रद्द करने वाला गतिरोध उत्पन्न होता है।

तथा:

MySQL 5.6 में, यह सुविधा अधिक सामान्य हो जाती है: आप एक इंडेक्स बनते समय टेबलों को पढ़ और लिख सकते हैं, और कई अन्य प्रकार के ALTER TABLE ऑपरेशंस को टेबल पर कॉपी किए बिना, DML ऑपरेशंस को ब्लॉक किए बिना, या दोनों के द्वारा किया जा सकता है। इस प्रकार MySQL 5.6 और उच्चतर में, हम आम तौर पर फास्ट इंडेक्स क्रिएशन के बजाय ऑनलाइन DDL के रूप में सुविधाओं के इस सेट को संदर्भित करते हैं।

से http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_fast_index_creation


फिर डेव के विश्लेषण को कैसे समझाया जा सकता है?
निखिल साहू

1
@ निखिलशाहु डेव स्पष्ट रूप से MySQL 5.6 पर परीक्षण नहीं कर रहे थे, लेकिन कुछ पुराने संस्करण पर। ध्यान दें कि 5.6 अभी तक इस बिंदु पर जारी नहीं किया गया था कि डेव ने अपने उत्तर के प्रारंभिक संशोधन को पोस्ट किया था।
मार्क अमेरी

+1। मेरा विश्लेषण MySQL 5.5 (नवीनतम जो 2013 में उपलब्ध था) पर था। मैं MySQL 5.6 में नई क्षमताओं को प्रतिबिंबित करने के लिए अपने उत्तर को अपडेट कर रहा हूं।
डेव डोपसन

3

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

जैसा कि मैंने उपरोक्त टिप्पणी में लिखा है, मुझे पीटी-ऑनलाइन-स्कीमा-उत्पादन में बदलाव के साथ कई अनुभव हैं। हमारे पास 20M + रिकॉर्ड और एक मास्टर की मुख्य तालिका है -> 2 केवल-पढ़ने के लिए दास। मैंने pt-online-स्कीमा-परिवर्तन के साथ कम से कम दर्जनों माइग्रेशन किए हैं एक नए कॉलम को जोड़ने से, चार्ट को बदलने से, कई सूचकांकों को जोड़ने से। हम प्रवास के समय में भी ट्रैफिक की बहुत अधिक मात्रा में सेवा करते हैं और हमें कोई हिचकी नहीं आई है। बेशक आपको उत्पादन पर चलने से पहले सभी लिपियों का पूरी तरह से परीक्षण करना होगा।

मैंने परिवर्तनों को 1 स्क्रिप्ट में बैचने की कोशिश की ताकि पीटी-ऑनलाइन-स्कीमा-परिवर्तन को केवल एक बार डेटा की प्रतिलिपि बनाना पड़े। और कॉलम नाम बदलने से बहुत सावधान रहें क्योंकि आप अपना डेटा ढीला कर देंगे। हालांकि, एक इंडेक्स जोड़ना ठीक होना चाहिए।


मैं आपकी अयोग्य सिफारिश से असहमत हूं pt-online-schema-change। यह बहुत अच्छा है, लेकिन कई स्थितियों के लिए ओवरकिल है जहां MySQL 5.6 + की ऑनलाइन DDL क्षमताएं पहले से ही ठीक हैं। इसकी सीमाएँ भी हैं (जैसे ट्रिगर्स के साथ अच्छी तरह से नहीं खेलना), और एक स्कीमा परिवर्तन प्रगति पर है, जबकि मूल तालिका में प्रति डालने के लिए आवश्यक लेखन की मात्रा दोगुनी हो जाती है। यह आपकी डिस्क को एक साधारण ऑनलाइन स्कीमा परिवर्तन की तुलना में काफी अधिक कर देगा, और इसलिए उन परिस्थितियों में "आपकी साइट को नीचे लाने" की क्षमता है जहां सिर्फ स्कीमा बदलने से साधारण तरीके से काम करना ठीक होगा।
मार्क अमेरी

मैंने उस समय पीटी-ऑनलाइन-स्कीमा-परिवर्तन के साथ अपने वास्तविक अनुभव के आधार पर लिखा था इसलिए मुझे यकीन नहीं है कि आप मेरी सिफारिश को "अयोग्य" क्यों कहेंगे। हम किसी भी समय साइट पर कम से कम 1000+ आगंतुक आ रहे थे जब मैंने स्कीमा में बदलाव किया, और निश्चित रूप से, डिस्क आईओ कर लगा रहा था, लेकिन हमारी साइट नीचे नहीं गई। अच्छी कैशिंग होने के साथ ही मदद भी की। मैंने MySQL 5.6+ ऑनलाइन DDL का उपयोग नहीं किया है, लेकिन मेरे अनुभव से, pt-online-schema-change ने हमारे मामले में अच्छा काम किया है।
एलेक्स ले

1
@AlexYe Yikes, मेरा मतलब था "बिना आरक्षण के अर्थ में" अयोग्य "," किसी के द्वारा दिया गया "के बजाए, जो टिप्पणी करने के योग्य नहीं है" - बाद की व्याख्या मेरे पास तब तक नहीं हुई जब तक कि मैंने आपकी टिप्पणी और निश्चित रूप से नहीं देखी। 'टी क्या मैं इरादा! यानी मैं कह रहा था कि जहां pt-online-schema-changeएक उपयोगी उपकरण है, वहां बहुत सारी स्थितियां हैं जिनमें साधारण ऑनलाइन डीडीएल सिर्फ उतना ही अच्छा और एक मुट्ठी भर है जहां यह बेहतर है, इसलिए किसी भी सिफारिश को सार्वभौमिक के बजाय सावधानीपूर्वक सामना करना चाहिए।
मार्क अमेरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.