Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

इनोडब में ताला लगाने के लिए डमी गाइड

हाल ही में, अजीब लॉकिंग मुद्दे (संस्करण 5.1.37) पर MySQL समर्थन के साथ काम करने से मेरे नोट्स यहां दिए गए हैं:

बदली जा रही पंक्तियों तक पहुंचने के लिए सभी पंक्तियों और अनुक्रमणिका प्रविष्टियों को लॉक कर दिया जाएगा। इसमें शामिल है:

http://dev.mysql.com/doc /refman/5.1/hi/innodb-locks-set.html

"एक लॉकिंग रीड, एक अद्यतन, या एक DELETE आमतौर पर प्रत्येक इंडेक्स रिकॉर्ड पर रिकॉर्ड लॉक सेट करता है जो SQL स्टेटमेंट की प्रोसेसिंग में स्कैन किया जाता है। इससे कोई फर्क नहीं पड़ता कि स्टेटमेंट में WHERE स्थितियां हैं जो पंक्ति को बाहर कर देंगी। InnoDB करता है सटीक WHERE स्थिति याद नहीं है, लेकिन केवल यह जानता है कि कौन सी अनुक्रमणिका श्रेणियां स्कैन की गई थीं। ... यदि आपके पास अपने कथन के लिए उपयुक्त कोई अनुक्रमणिका नहीं है और MySQL को कथन को संसाधित करने के लिए पूरी तालिका को स्कैन करना होगा, तो तालिका की प्रत्येक पंक्ति लॉक हो जाती है, जिसमें टर्न अन्य उपयोगकर्ताओं के सभी इंसर्ट को टेबल पर ब्लॉक कर देता है।"

यह है। एक समाधान जो अक्सर सहायक होता है वह है:

अद्यतन करें जो कुछ भी कुछ भी सेट करें जहां प्राथमिक कुंजी है (प्राथमिक कुंजी का चयन करें जहां प्राथमिक कुंजी द्वारा बाधाओं का आदेश दिया गया है);

आंतरिक चयन को ताले लेने की आवश्यकता नहीं है और अद्यतन के लिए अद्यतन करने के लिए अद्यतन के पास कम काम होगा। खंड दर क्रम यह सुनिश्चित करता है कि अद्यतन प्राथमिक कुंजी क्रम में किया गया है ताकि यह InnoDB के भौतिक क्रम से मेल खा सके, इसे करने का सबसे तेज़ तरीका।

जहां बड़ी संख्या में पंक्तियाँ शामिल हैं, जैसा कि आपके मामले में है, चयन परिणाम को अस्थायी तालिका में फ़्लैग कॉलम के साथ संग्रहीत करना बेहतर हो सकता है। फिर अस्थायी तालिका से चयन करें जहां प्रत्येक बैच प्राप्त करने के लिए ध्वज सेट नहीं है। 1000 या 10000 की सीमा के साथ अद्यतन चलाएँ और अद्यतन के बाद बैच के लिए ध्वज सेट करें। सीमाएं लॉकिंग की मात्रा को एक सहनीय स्तर तक रखेंगी जबकि चुनिंदा कार्य केवल एक बार करना होगा। प्रत्येक बैच के बाद तालों को छोड़ने के लिए प्रतिबद्ध।

आप अपडेट के प्रत्येक बैच को करने से पहले एक अनइंडेक्स्ड कॉलम का एक चुनिंदा योग करके भी इस काम को तेज कर सकते हैं। यह डेटा पेजों को बिना लॉक किए बफर पूल में लोड करेगा। फिर लॉकिंग कम समय के लिए चलेगी क्योंकि कोई डिस्क रीड नहीं होगी।

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

यदि संभव हो तो रीड कमिटेड ट्रांजेक्शन आइसोलेशन मोड का उपयोग करें। देखें:

http://dev.mysql.com/doc/refman /5.1/hi/set-transaction.html

उस कम लॉकिंग को प्राप्त करने के लिए पंक्ति-आधारित बाइनरी लॉगिंग (डिफ़ॉल्ट स्टेटमेंट आधारित बाइनरी लॉगिंग के बजाय) के उपयोग की आवश्यकता होती है।

दो ज्ञात मुद्दे:

  1. उपश्रेणियाँ कभी-कभी आदर्श रूप से अनुकूलित से कम हो सकती हैं। इस मामले में यह एक अवांछित आश्रित सबक्वायरी थी - मैंने एक सबक्वायरी का उपयोग करने के लिए जो सुझाव दिया वह इस मामले में विकल्प की तुलना में अनुपयोगी साबित हुआ।

  2. डिलीट और अपडेट में क्वेरी प्लान की रेंज चुनिंदा स्टेटमेंट के समान नहीं होती है, इसलिए कभी-कभी परिणामों को मापे बिना उन्हें ठीक से ऑप्टिमाइज़ करना मुश्किल होता है ताकि वे वास्तव में क्या कर रहे हों।

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

http://bugs.mysql.com/bug.php?id=36569




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पेश है पिछले महीने के योग के लिए एक नया कॉलम

  2. डेटाबेस से यादृच्छिक पंक्तियों को कैसे प्रतिध्वनित करें?

  3. स्क्रिप्ट में MySQL ट्रैफ़िक को एन्क्रिप्ट करना

  4. Laravel में ईमेल लिंक को फिर से भेजें फंक्शन कैसे करें?

  5. डुप्लिकेट कुंजी अद्यतन पर सशर्त