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

MySQL:स्थायी रूप से तालिका मेटाडेटा लॉक की प्रतीक्षा कर रहा है

स्वीकृत समाधान, दुर्भाग्य से, गलत है . जहाँ तक यह कहा गया है, यह सही है,

यह वास्तव में है (लगभग निश्चित रूप से; नीचे देखें) क्या करना है। लेकिन फिर यह सुझाव देता है,

...और 1398 नहीं ताला के साथ संबंध। ऐसा कैसे हो सकता है? 1398 कनेक्शन है प्रतीक्षा ताला के लिए। इसका मतलब है कि यह अभी तक नहीं है ताला, और इसलिए, इसे मारने से कुछ भी लाभ नहीं होता है। लॉक रखने की प्रक्रिया अभी भी लॉक को बनाए रखेगी, और अगला थ्रेड कुछ करने की कोशिश कर रहा है इसलिए भी स्टाल करें और उचित क्रम में "मेटाडेटा लॉक की प्रतीक्षा कर रहा है" दर्ज करें।

आपको इस बात की कोई गारंटी नहीं है कि "मेटाडेटा लॉक की प्रतीक्षा" (WFML) प्रक्रियाएं भी अवरुद्ध नहीं होंगी, लेकिन आप निश्चित हो सकते हैं कि केवल WFML प्रक्रियाओं को मारने से वास्तव में कुछ भी नहीं प्राप्त होगा। ।

असली कारण यह है कि दूसरी प्रक्रिया में अवरोध है , और अधिक महत्वपूर्ण बात, SHOW FULL PROCESSLIST आपको सीधे नहीं बताएगा कि यह कौन सा है

यह होगा आपको बताएं कि क्या प्रक्रिया कर रही है कुछ, हाँ। आमतौर पर यह काम करता है। यहां, लॉक रखने की प्रक्रिया कुछ नहीं कर रही है , और अन्य धागों के बीच छिप जाता है और कुछ नहीं कर रहा है।

इस मामले में अपराधी लगभग निश्चित रूप से है प्रक्रिया 1396 , जो 1398 की प्रक्रिया से पहले शुरू हुआ था और अब Sleep . में है राज्य, और 46 सेकंड के लिए किया गया है। चूंकि 1396 ने स्पष्ट रूप से वह सब किया जो उसे करने की आवश्यकता थी (जैसा कि इस तथ्य से साबित होता है कि यह अब सो रहा है, और 46 सेकंड के लिए ऐसा किया है, जहां तक ​​MySQL का संबंध है ), इससे पहले सोने के लिए कोई भी धागा ताला नहीं लगा सकता था (या 1396 भी रुक जाता था)।

महत्वपूर्ण :यदि आप एक सीमित उपयोगकर्ता के रूप में MySQL से जुड़े हैं, SHOW FULL PROCESSLIST होगा नहीं सभी प्रक्रियाओं को दिखाएं। तो लॉक को एक ऐसी प्रक्रिया द्वारा रोका जा सकता है जिसे आप नहीं देखते हैं।

बेहतर SHOW PROCESSLIST

SELECT ID, TIME, USER, HOST, DB, COMMAND, STATE, INFO
    FROM INFORMATION_SCHEMA.PROCESSLIST WHERE DB IS NOT NULL
    AND (`INFO` NOT LIKE '%INFORMATION_SCHEMA%' OR INFO IS NULL)
    ORDER BY `DB`, `TIME` DESC

उपरोक्त को केवल स्लीप अवस्था में प्रक्रियाओं को दिखाने के लिए ट्यून किया जा सकता है, और वैसे भी यह उन्हें अवरोही समय के अनुसार क्रमबद्ध करेगा, इसलिए लटकी हुई प्रक्रिया को खोजना आसान है (यह आमतौर पर Sleep है। "मेटाडेटा लॉक की प्रतीक्षा कर रहे" वाले से ठीक पहले एक आईएनजी।

महत्वपूर्ण बात

किसी भी "मेटाडेटा लॉक की प्रतीक्षा" प्रक्रिया को अकेले छोड़ दें ।

त्वरित और गंदा समाधान, वास्तव में अनुशंसित नहीं बल्कि त्वरित

सभीको मार डालो "स्लीप" स्थिति में प्रक्रियाएं, उसी डेटाबेस पर, जो सबसे पुराने से पुराने . हैं "मेटाडेटा लॉक की प्रतीक्षा में" स्थिति में धागा। यह है Arnaud Amaury किया होता:

  • प्रत्येक डेटाबेस के लिए जिसमें WaitingForMetadataLock में कम से कम एक थ्रेड है:
    • WFML में उस DB पर सबसे पुराना कनेक्शन Z सेकंड पुराना निकला
    • उस DB और Z से पुराने सभी "स्लीप" थ्रेड्स को अवश्य जाना चाहिए। सबसे नए से शुरू करें, बस मामले में।
    • यदि उस DB पर एक पुराना और बिना नींद वाला कनेक्शन मौजूद है, तो हो सकता है कि वह ताला पकड़े हुए हो, लेकिन यह कुछ कर रहा हो . आप निश्चित रूप से इसे मार सकते हैं, लेकिन विशेष रूप से यदि यह एक अद्यतन/सम्मिलित करें/हटाएं, तो आप अपने जोखिम पर ऐसा करते हैं।

सौ में से निन्यानबे बार, मारा जाने वाला धागा सबसे छोटा होता है नींद की स्थिति में उन लोगों में से जो बड़े हैं मेटाडेटा लॉक की प्रतीक्षा कर रहे पुराने की तुलना में:

TIME     STATUS
319      Sleep
205      Sleep
 19      Sleep                      <--- one of these two "19"
 19      Sleep                      <--- and probably this one(*)
 15      Waiting for metadata lock  <--- oldest WFML
 15      Waiting for metadata lock
 14      Waiting for metadata lock

(*) TIME ऑर्डर में वास्तव में मिलीसेकंड है, या तो मुझे बताया गया था, यह उन्हें नहीं दिखाता है। इसलिए जबकि दोनों प्रक्रियाओं का समय मान 19 है, सबसे कम उम्र का होना चाहिए।

अधिक केंद्रित समाधान

SHOW ENGINE INNODB STATUS चलाएं और "लेनदेन" अनुभाग देखें। दूसरों के बीच, आपको कुछ ऐसा मिलेगा

TRANSACTION 1701, ACTIVE 58 sec;2 lock struct(s), heap size 376, 1 row lock(s), undo log entries 1
MySQL thread id 1396, OS thread handle 0x7fd06d675700, query id 1138 hostname 1.2.3.4 whatever;

अब आप SHOW FULL PROCESSLIST . से चेक करें थ्रेड आईडी 1396 अपने #1701 लेनदेन के साथ क्या कर रहा है। संभावना है कि यह "स्लीप" स्थिति में है। तो:एक सक्रिय लेनदेन (# 1701) एक सक्रिय लॉक के साथ, इसने कुछ बदलाव भी किए हैं क्योंकि इसमें एक पूर्ववत लॉग प्रविष्टि है ... लेकिन वर्तमान में निष्क्रिय है। वह और कोई अन्य धागा नहीं है जिसे आपको मारने की आवश्यकता है। उन परिवर्तनों को खोना।

याद रखें कि MySQL में कुछ नहीं करने का मतलब सामान्य रूप से कुछ भी नहीं करना है। यदि आप MySQL से कुछ रिकॉर्ड प्राप्त करते हैं और FTP अपलोड के लिए CSV बनाते हैं, तो FTP अपलोड के दौरान MySQL कनेक्शन निष्क्रिय रहता है।

वास्तव में यदि MySQL और MySQL सर्वर का उपयोग करने वाली प्रक्रिया एक ही मशीन पर है, वह मशीन Linux चलाती है, और आपके पास रूट विशेषाधिकार हैं, तो यह पता लगाने का एक तरीका है कि कौन सी प्रक्रिया है कनेक्शन है जिसने लॉक का अनुरोध किया है। यह बदले में निर्धारित करने की अनुमति देता है (सीपीयू उपयोग से या, कम से कम, strace -ff -p pid ) क्या वह प्रक्रिया वास्तव में . है कुछ करना या न करना, यह तय करने में मदद करने के लिए कि मारना सुरक्षित है या नहीं।

ऐसा क्यों होता है?

मैं इसे "लगातार" या "पूल किए गए" MySQL कनेक्शन का उपयोग करने वाले वेबएप के साथ देख रहा हूं, जो आजकल आमतौर पर बहुत कम समय बचाते हैं:वेबएप इंस्टेंस समाप्त हो गया, लेकिन कनेक्शन नहीं हुआ , इसलिए इसका ताला अभी भी जीवित है... और बाकी सभी को अवरुद्ध कर रहा है।

एक और दिलचस्प तरीका जो मैंने पाया है, ऊपर की परिकल्पना में, कुछ पंक्तियों को वापस करने वाली क्वेरी को चलाने के लिए, और उनमें से केवल कुछ को पुनः प्राप्त करें . यदि क्वेरी "ऑटो-क्लीन" पर सेट नहीं है (हालाँकि अंतर्निहित डीबीए इसे करता है), यह कनेक्शन को खुला रखेगा और टेबल पर पूर्ण लॉक को जाने से रोकेगा। मेरे साथ ऐसा कोड के एक टुकड़े में हुआ था जिसने सत्यापित किया था कि क्या उस पंक्ति का चयन करके एक पंक्ति मौजूद है और यह सत्यापित किया गया है कि इसमें कोई त्रुटि है (मौजूद नहीं है) या नहीं (यह मौजूद होना चाहिए), लेकिन वास्तव में पंक्ति को पुनर्प्राप्त किए बिना

डीबी से पूछें

यदि आपके पास हाल ही में MySQL है, तो अपराधी को पाने का दूसरा तरीका, लेकिन बहुत हाल का नहीं चूंकि इसे बहिष्कृत किया जा रहा है , है (सूचना स्कीमा पर आपको फिर से विशेषाधिकारों की आवश्यकता है)

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS 
     WHERE LOCK_TRX_ID IN 
        (SELECT BLOCKING_TRX_ID FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS);

वास्तविक समाधान, समय और कार्य की आवश्यकता है

समस्या आमतौर पर इस वास्तुकला के कारण होती है:

जब वेबएप मर जाता है, या वेबएप लाइटवेट थ्रेड इंस्टेंस मर जाता है, कंटेनर/कनेक्शन पूल नहीं हो सकता है . और यह कंटेनर . है जो कनेक्शन को खुला रखता है, तो जाहिर है कि कनेक्शन बंद नहीं होता है। काफी अनुमानित रूप से, MySQL ऑपरेशन को पूर्ण नहीं मानता

यदि वेबएप अपने आप साफ नहीं हुआ (कोई ROLLBACK . नहीं या COMMIT लेन-देन के लिए, कोई UNLOCK TABLES . नहीं , आदि), फिर उस वेबएप ने जो कुछ भी करना शुरू किया वह अभी भी विद्यमान है , और हो सकता है कि अभी भी बाकी सभी को ब्लॉक कर रहा हो।

फिर दो उपाय हैं। इससे भी बुरा यह है कि निष्क्रिय टाइमआउट कम करें . लेकिन लगता है कि क्या होता है यदि आप दो प्रश्नों के बीच बहुत लंबा इंतजार करते हैं (बिल्कुल:"MySQL सर्वर चला गया है")। फिर आप mysql_ping . का उपयोग कर सकते हैं यदि उपलब्ध हो (जल्द ही पदावनत किया जाएगा। समाधान हैं पीडीओ के लिए। या आप उस . की जांच कर सकते हैं त्रुटि, और यदि ऐसा होता है तो कनेक्शन को फिर से खोलें (यह पायथन तरीका है)। तो - एक छोटे से प्रदर्शन शुल्क के लिए - यह संभव है।

बेहतर, होशियार समाधान लागू करने के लिए कम सीधा है। सभी पंक्तियों को पुनः प्राप्त करने या सभी क्वेरी संसाधनों को मुक्त करने, सभी अपवादों को पकड़ने और उनके साथ ठीक से निपटने, या यदि संभव हो तो, लगातार कनेक्शन को पूरी तरह से छोड़ दें . प्रत्येक उदाहरण को अपना कनेक्शन बनाने दें या एक स्मार्ट का उपयोग करें पूल ड्राइवर (PHP PDO में, PDO::ATTR_PERSISTENT . का प्रयोग करें स्पष्ट रूप से false पर सेट करें ) वैकल्पिक रूप से (जैसे PHP में) आप विनाश कर सकते हैं और अपवाद हैंडलर लेनदेन करने या वापस लेन-देन करके और स्पष्ट तालिका अनलॉक जारी करके कनेक्शन को साफ कर सकते हैं।

मुझे मौजूदा परिणाम सेट संसाधनों को मुक्त करने के लिए क्वेरी करने के तरीके के बारे में पता नहीं है; सहेजें . का एकमात्र तरीका होगा उन संसाधनों को एक निजी सरणी में।



  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. MAX () - MySQL में एक कॉलम में अधिकतम मान का पता लगाएं

  3. क्या मैं Java PooledConnections का सही उपयोग कर रहा हूँ?

  4. MySQL स्टोर संबंध (परिवार) ट्री

  5. SQL - कुछ पंक्तियों का योग, अन्य पंक्तियों का घटा योग