फिक्सिंग "लॉक वेट टाइमआउट पार हो गया; एक 'अटक' Mysql तालिका के लिए "पुनः आरंभ लेनदेन" की कोशिश करो?


131

एक स्क्रिप्ट से मैंने अपने स्थानीय डेटाबेस के लिए इस तरह के एक प्रश्न को हजारों बार भेजा:

update some_table set some_column = some_value

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

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

Lock wait timeout exceeded; try restarting transaction

यह एक अंतरंग सारणी है, इसलिए अटका हुआ लेन-देन संभवतः निहित है। मैं इस तालिका को कैसे ठीक कर सकता हूं और इसमें से फंसे लेनदेन को निकाल सकता हूं?


3
का आउटपुट क्या है SHOW FULL PROCESSLIST?
वोल्फ

यह केवल SHOW FULL PROCESSLIST कमांड दिखाता है, और कुछ नहीं। यह एक स्थानीय विकास डेटाबेस है। इस पर कुछ नहीं चल रहा है। कमांड लाइन पर मुझे 'लॉक वेट ..' त्रुटि संदेश मिला, जब मैंने सूचकांक को वहां से छोड़ने की कोशिश की।
टॉम

उस स्थिति में आप शायद अलग-अलग लेन-देन में 2 अलग-अलग कनेक्शन बना रहे हैं, जिसे प्रत्येक अभिभावक को इंतजार करना होगा।
वोल्फ

मैंने बाद में कोई लेनदेन नहीं किया। मैंने स्क्रिप्ट को मार दिया, मशीन को रिबूट किया और कमांड लाइन से चारों ओर देखने के लिए लॉग इन किया। Mysql कमांड लाइन क्लाइंट को छोड़कर डेटाबेस में और कुछ भी उपयोग नहीं किया गया है, इसलिए कुछ तालिका में अटक गया होगा।
टॉम

जवाबों:


143

मेरे पास एक समान समस्या थी और इसे उन थ्रेड्स की जांच करके हल किया जो चल रहे हैं। रनिंग थ्रेड्स देखने के लिए mysql कमांड लाइन इंटरफेस में निम्न कमांड का उपयोग करें:

SHOW PROCESSLIST;

यदि आप mysql कमांड लाइन इंटरफ़ेस तक पहुंच नहीं रखते हैं, तो इसे phpMyAdmin से भी भेजा जा सकता है।
यह संबंधित आईडी और निष्पादन समय के साथ थ्रेड्स की एक सूची प्रदर्शित करेगा, इसलिए आप उन थ्रेड्स को मार सकते हैं जिन्हें निष्पादित करने में बहुत अधिक समय लग रहा है। PhpMyAdmin में आपके पास KILL का उपयोग करके थ्रेड्स को रोकने के लिए एक बटन होगा, यदि आप कमांड लाइन इंटरफ़ेस का उपयोग कर रहे हैं तो थ्रेड आईडी के बाद KILL कमांड का उपयोग करें, जैसे निम्न उदाहरण में:

KILL 115;

यह संबंधित थ्रेड के लिए कनेक्शन को समाप्त कर देगा।


36
नोट करें! यह इस समस्या से संबंधित कई SO थ्रेड्स में से एक पर किसी ने उल्लेख किया था: कभी-कभी जिस प्रक्रिया ने तालिका को लॉक किया है वह प्रक्रियासूची में सोते हुए दिखाता है! मैं अपने बालों को तब तक फाड़ रहा था जब तक कि मैंने उन सभी धागों को नहीं मार दिया, जो प्रश्न में डेटाबेस में खुले थे, सो रहे थे या नहीं। अंत में टेबल को अनलॉक किया और अपडेट क्वेरी को चलने दें। टिप्पणीकार ने कुछ इस तरह का उल्लेख किया "कभी-कभी एक MySQL थ्रेड एक टेबल को लॉक करता है, फिर सोता है जबकि यह कुछ गैर-MySQL से संबंधित होने की प्रतीक्षा करता है।"
एरिक एल।

(मैं अपने ही जवाब है कि सोचा टुकड़ा बाहर मांस के लिए जोड़ा यहाँ , एक संबंधित सवाल पर)
एरिक एल

इससे मुझे मदद मिली। मेरे पास PHPStorm डेटाबेस मैनेजमेंट / क्वेरी फ़ीचर द्वारा बनाए गए स्लीपिंग थ्रेड्स हैं।
एजाज

महान! मेरे पास 5 घंटे से एक छिपी हुई प्रक्रिया थी जिसे मैं पहचान सकता था और मार सकता था।
एल्डो

2
यह एक संक्रमित घाव पर नलिका से अधिक किसी भी तरह का एक समाधान नहीं है एक समाधान है। अंतर्निहित जड़ समस्या को संबोधित नहीं कर रहे हैं।
user2914191

55

आप वर्तमान में चल रहे लेनदेन की जांच कर सकते हैं

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`

आपका लेन-देन पहले में से एक होना चाहिए, क्योंकि यह सूची में सबसे पुराना है। अब बस से मान लें trx_mysql_thread_idऔर इसे KILLकमांड भेजें :

KILL 1234;

यदि आप अनिश्चित हैं कि कौन सा लेन-देन आपका है, तो पहली क्वेरी को बहुत बार दोहराएं और देखें कि कौन सा लेनदेन जारी है।


आपको उस खाते को चलाने के लिए रूट अकाउंट का उपयोग करने की आवश्यकता हो सकती है, यह देखने के लिए कि कौन सा लेन-देन वास्तव में एक्सेस टेबल से दूसरे को रोक रहा है
tom10271

40

तालों के लिए InnoDB स्थिति की जाँच करें

SHOW ENGINE InnoDB STATUS;

MySQL ओपन टेबल चेक करें

SHOW OPEN TABLES WHERE In_use > 0;

लंबित InnoDB लेनदेन की जाँच करें

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`; 

लॉक निर्भरता की जांच करें - क्या ब्लॉक करता है

SELECT * FROM `information_schema`.`innodb_locks`;

उपरोक्त परिणामों की जांच करने के बाद, आपको यह देखने में सक्षम होना चाहिए कि लॉकिंग क्या है।

समस्या का मूल कारण आपके कोड में भी हो सकता है - कृपया संबंधित कार्यों की जांच खासतौर पर एनोटेशन के लिए करें यदि आप JPA जैसे हाइबरनेट का उपयोग करते हैं।

उदाहरण के लिए, जैसा कि यहां बताया गया है , निम्नलिखित एनोटेशन का दुरुपयोग डेटाबेस में ताले का कारण हो सकता है:

@Transactional(propagation = Propagation.REQUIRES_NEW) 

4
आपको बहुत - बहुत धन्यवाद! रनिंग SELECT * FROM information_schema.innodb_trx t JOIN information_schema.processlist p ON t.trx_mysql_thread_id = p.idसे अपराधी का पता चला: लॉकिंग थ्रेड मेरे आईपी पते पर आया था ... मैं एक डिबग कंसोल को बंद करना भूल गया था जिसे मैंने लेन-देन के बीच में छोड़ दिया था ...
इलायस स्ट्रीपल

40

यह मेरे साथ तब होने लगा जब मेरे डेटाबेस का आकार बढ़ता गया और मैं इस पर बहुत अधिक लेनदेन कर रहा था।

सच्चाई यह है कि आपके प्रश्नों या आपके DB को ऑप्टिमाइज़ करने का कोई तरीका है, लेकिन फ़िक्स के चारों ओर इन 2 प्रश्नों को आज़माएं।

इसे चलाओ:

SET GLOBAL innodb_lock_wait_timeout = 5000; 

और फिर यह:

SET innodb_lock_wait_timeout = 5000; 

2
संदर्भ लिंक: innodb_lock_wait_timeout
culix

1
मैं बहुत व्यस्त 11GB डेटाबेस चला रहा हूं। यह केवल एक चीज है जिसने मेरे लिए काम किया है, धन्यवाद!
डोंगेमस

यदि आप उन्हें हमेशा के लिए नहीं रखना चाहते हैं तो मूल्यों को उसके पिछले मूल्यों में बदलना याद रखें।
रिकार्डो मार्टिंस

इसका मतलब यह है कि मेरे कुछ उपयोगकर्ताओं को अधिक धीमा अनुभव होगा?
अर्नोल्ड रोआ

9

जब आप लेन-देन के लिए कनेक्शन स्थापित करते हैं, तो आप लेन-देन करने से पहले एक लॉक प्राप्त करते हैं। यदि ताला प्राप्त करने में सक्षम नहीं है, तो आप कुछ समय के लिए प्रयास करें। यदि लॉक अभी भी प्राप्त करने योग्य नहीं है, तो लॉक प्रतीक्षा समय पार हो गई त्रुटि को फेंक दिया गया है। आप लॉक क्यों नहीं प्राप्त कर पाएंगे कि आप कनेक्शन बंद नहीं कर रहे हैं। इसलिए, जब आप दूसरी बार लॉक प्राप्त करने का प्रयास कर रहे हैं, तो आप लॉक का अधिग्रहण नहीं कर पाएंगे क्योंकि आपका पिछला कनेक्शन अभी भी बंद है और लॉक को पकड़े हुए है।

समाधान: बंद करने के लिए कनेक्शन setAutoCommit(true)( या आपके डिजाइन के अनुसार) को बंद करें।


7

MySQL को पुनरारंभ करें, यह ठीक काम करता है।

लेकिन सावधान रहें कि यदि ऐसी कोई क्वेरी अटक गई है, तो कहीं न कहीं समस्या है:

  • आपकी क्वेरी में (गलत वर्ण, कार्टेसियन उत्पाद, ...)
  • बहुत सारे रिकॉर्ड संपादित करने के लिए
  • जटिल जोड़ या परीक्षण (MD5, सबस्ट्रिंग LIKE %...%, आदि)
  • डेटा संरचना की समस्या
  • विदेशी कुंजी मॉडल (चेन / लूप लॉकिंग)
  • गलत डेटा

जैसा कि @syedrakib ने कहा, यह काम करता है लेकिन यह उत्पादन के लिए लंबे समय तक रहने वाला समाधान नहीं है।

खबरदार: पुनरारंभ करना असंगत स्थिति के साथ आपके डेटा को प्रभावित कर सकता है।

इसके अलावा, आप देख सकते हैं कि MySQL EXPLAIN कीवर्ड के साथ आपकी क्वेरी को कैसे संभालता है और देखें कि क्वेरी (इंडेक्स, जटिल परीक्षण, ...) को गति देने के लिए कुछ संभव है या नहीं।


धन्यवाद। आपने सीधे मेरे मुद्दे को हल नहीं किया लेकिन मैं टेबल लॉक से पीड़ित था और यह बहुत बुरा था। यह एकमात्र पोस्ट है जो पूरे इंटरनेट को मानता है, जो मुझे विदेशी कुंजी की जांच करने के लिए विचार की ओर ले जाता है। इसलिए मुझे पता चला कि प्राथमिक कुंजी की कुंजी 11 थी और विदेशी चाबियां 10. मुझे नहीं पता कि ऐसा कैसे हो सकता है और सब कुछ पहले क्यों काम किया।
एस्केपनेटस्केप

@EscapeNetscape आपका स्वागत है, मुझे खुशी है कि इस छोटे से उत्तर से आपको मदद मिली :)
बेंज

3

गोटो mysql में प्रक्रिया करता है।

इसलिए देख सकते हैं कि अभी भी काम करना बाकी है।

किसी विशेष प्रक्रिया को मारें या प्रक्रिया पूरी होने तक प्रतीक्षा करें।


7
यह समस्या का समाधान करता है। लेकिन यह एक LIVE प्रोडक्शन सर्वर के लिए एक समाधान नहीं हो सकता है ...... हम इस डेडलॉक हैंडलिंग को कैसे आउटपुट कर सकते हैं? या हम इस गतिरोध को कैसे होने से बचा सकते हैं?
रकीब

1
ठीक है, ऐसा होता है कि यहां तक ​​कि पूर्ण रूप से अच्छी तरह से गठित और सही ढंग से बच गए mysql प्रश्नों के साथ, जो डेवलपर द्वारा भी नहीं लिखे गए हैं, लेकिन फ्रेमवर्क के सक्रिय-रिकॉर्ड इंटरफ़ेस द्वारा, लॉक वेट टाइमआउट मुद्दे कभी भी हो सकते हैं। इसलिए मैं उचित mysql क्वेरी नहीं लिख रहा हूँ यहाँ एक कारक है।
राकिब

1

मैं "अद्यतन" के साथ एक ही समस्या में भाग गया -statement। मेरा समाधान केवल टेबल के लिए phpMyAdmin में उपलब्ध संचालन के माध्यम से चलाना था। मैंने टेबल को अनुकूलित किया, फ्लश किया और डीफ़्रैग्मेन्ट किया (उस क्रम में नहीं)। तालिका को छोड़ने और मेरे लिए इसे बैकअप से पुनर्स्थापित करने की आवश्यकता नहीं है। :)


1
यह समस्या को हल कर सकता है। लेकिन हर बार ऐसी त्रुटि होने पर LIVE प्रोडक्शन सर्वर के लिए कोई समाधान नहीं हो सकता है ...... हम इस डेडलॉक हैंडलिंग को कैसे आउटपुट कर सकते हैं? या हम इस गतिरोध को कैसे होने से बचा सकते हैं?
रकीब

1

मेरी भी यही समस्या थी। मुझे लगता है कि यह SQL के साथ एक डेडलॉक मुद्दा था। आप टास्क मैनेजर से SQL प्रक्रिया को बंद करने के लिए बाध्य कर सकते हैं। यदि वह इसे ठीक नहीं करता है, तो बस अपने कंप्यूटर को पुनरारंभ करें। आपको तालिका को छोड़ने और डेटा को पुनः लोड करने की आवश्यकता नहीं है।


यह समस्या का समाधान करता है। लेकिन यह एक LIVE प्रोडक्शन सर्वर के लिए एक समाधान नहीं हो सकता है ...... हम इस डेडलॉक हैंडलिंग को कैसे आउटपुट कर सकते हैं? या हम इस गतिरोध को कैसे होने से बचा सकते हैं?
रकीब

अपाचे और उसकी सेवाओं (या कम से कम MySQL) को फिर से शुरू करें, रिबूट करने की कोई आवश्यकता नहीं है
Amjo

1

जब मैं रिकॉर्ड के एक निश्चित समूह (वेब ​​सर्वर पर MySQL के लिए ODBC कनेक्शन के साथ MS Access का उपयोग करके) को हटाने की कोशिश कर रहा था, तो मुझे यह समस्या थी। आमतौर पर मैं MySQL से कुछ रिकॉर्ड्स को हटा देता था, फिर अपडेटेड रिकॉर्ड्स (कैस्केड को हटाकर कई संबंधित रिकॉर्ड्स को बदल देता था, यह स्ट्रीमलाइन एक ही रिकॉर्ड डिलीट करने के लिए सभी संबंधित रिकॉर्ड्स को डिलीट कर देता है)।

मैंने तालिका (ऑप्टिमाइज़, फ्लश, आदि) के लिए phpMyAdmin में उपलब्ध संचालन के माध्यम से चलाने की कोशिश की, लेकिन जब मैंने फ्लश करने की कोशिश की तो मुझे RELOAD त्रुटि की आवश्यकता हुई। चूँकि मेरा डेटाबेस एक वेब सर्वर पर है, मैं डेटाबेस को पुनः आरंभ नहीं कर सका। बैकअप से पुनर्स्थापित करना कोई विकल्प नहीं था।

मैंने वेब पर cPanel mySQL एक्सेस पर रिकॉर्ड के इस समूह के लिए डिलीट क्वेरी चलाने की कोशिश की। एक ही त्रुटि संदेश मिला।

मेरा समाधान: मैंने सन (ओरेकल) मुक्त MySQL क्वेरी ब्राउज़र (जो मैंने पहले अपने कंप्यूटर पर स्थापित किया था) का उपयोग किया और वहां डिलीट क्वेरी को चलाया। इसने तुरंत काम किया, समस्या हल हो गई। मैं तब ओडीबीसी एक्सेस टू माईएसक्यूएल कनेक्शन का उपयोग करके एक बार फिर से फंक्शन का उपयोग करने में सक्षम था।


-2

ठीक कर दिया।

सुनिश्चित करें कि आपके पास क्वेरी में बेमेल डेटा प्रकार सम्मिलित नहीं है। मेरे पास एक ऐसा मुद्दा था जहां मैं "उपयोगकर्ता ब्राउज़र एजेंट डेटा" में कोशिश कर रहा था VARCHAR(255)और इस लॉक के साथ समस्या हो रही थी लेकिन जब मैंने इसे बदल दिया तो TEXT(255)इसे ठीक कर दिया।

तो सबसे अधिक संभावना है कि यह डेटा प्रकार का बेमेल है।


-151

मैंने टेबल को गिराकर और बैकअप से इसे पुनर्स्थापित करके समस्या को हल किया।


20
संयोग से, यह उत्तर SO के सर्वकालिक सबसे कम-स्कोर वाले "स्वीकृत" उत्तर होने का सम्मान जीतता है ! Ed
ashleedawg

1
यह भी सामान्य तौर पर सबसे कम स्कोर वाला उत्तर है
बॉब कर्मन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.