“लॉक वेट टाइमआउट पार हो जाना; हालांकि मैं लेन-देन का उपयोग नहीं कर रहा हूं, फिर भी लेनदेन को पुनः आरंभ करने का प्रयास करें


267

मैं निम्नलिखित MySQL UPDATEस्टेटमेंट चला रहा हूं :

mysql> update customer set account_import_id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

मैं लेन-देन का उपयोग नहीं कर रहा हूं, इसलिए मुझे यह त्रुटि क्यों मिलेगी? मैंने अपने MySQL सर्वर को पुनः आरंभ करने की भी कोशिश की और इससे मदद नहीं मिली।

तालिका में 406,733 पंक्तियाँ हैं।

जवाबों:


211

आप लेन-देन का उपयोग कर रहे हैं; ऑटोकॉमिट लेन-देन को अक्षम नहीं करता है, यह सिर्फ बयान के अंत में उन्हें स्वचालित रूप से प्रतिबद्ध करता है।

क्या हो रहा है, कुछ अन्य धागे कुछ रिकॉर्ड पर एक रिकॉर्ड लॉक कर रहे हैं (आप तालिका में हर रिकॉर्ड को अपडेट कर रहे हैं!) बहुत लंबे समय के लिए, और आपका धागा समयबद्ध हो रहा है।

आप जारी करके घटना के अधिक विवरण देख सकते हैं

SHOW ENGINE INNODB STATUS

घटना के बाद ( sqlसंपादक में)। आदर्श रूप से एक शांत परीक्षण-मशीन पर ऐसा करें।


1
क्या आउटपुट को किसी फ़ाइल में सहेजने का कोई तरीका है? मैंने SHOW इंजन INNODB STATUS \ G> innodb_stat.txt की कोशिश की, लेकिन काम नहीं कर रहा है।
yantaq

14
कमांड लाइन से: mysql [क्रेडेंशियल्स डालें] -e "SHOW इंजन INNODB STATUS \ G"> innodb_stat.txt
आदरणीय

यदि कई mysql थ्रेड (या प्रक्रिया) व्यस्त हैं, उदाहरण के लिए कुछ क्वेरी को बहुत लंबे समय की आवश्यकता है, तो आपको processनिष्क्रिय होने के लिए कुछ इंतजार करना होगा। यदि हां, तो आपको यह त्रुटि मिल सकती है। क्या मैं सही हू?
ज़ुगुओवेई

6
एक ही लेन-देन के दौरान एक ही पंक्ति में एकाधिक (2+) अद्यतन क्वेरी चलाने से भी यह त्रुटि होगी।
ऑकलाइनर

Python MySQL कनेक्टर का उपयोग connection.commit()करने वालों के लिए INSERTया UPDATEआपके द्वारा अभी-अभी शूट किया गया है।
AER

334

MySQL में लॉक टेबल के लिए UNLOCK को कैसे लागू करें:

इस तरह से ताले को तोड़ने से डेटाबेस में एटमैलिटी हो सकती है जो कि लॉक होने वाले एसक्यूएल स्टेटमेंट पर लागू नहीं किया जा सकता है।

यह हैकिश है, और उचित समाधान आपके आवेदन को ठीक करना है जो ताले का कारण बना। हालांकि, जब डॉलर लाइन पर होते हैं, तो एक तेज किक से चीजें फिर से बढ़ेंगी।

1) MySQL दर्ज करें

mysql -u your_user -p

2) चलो बंद तालिकाओं की सूची देखें

mysql> show open tables where in_use>0;

3) चलो वर्तमान प्रक्रियाओं की सूची देखते हैं, उनमें से एक आपकी तालिका को बंद कर रही है

mysql> show processlist;

4) इन प्रक्रियाओं में से एक को मार डालो

mysql> kill <put_process_id_here>;

14
यह खतरनाक और हैकिश है। एक उचित समाधान आपके आवेदन को ठीक करना है।
Zenexer

71
बकवास, यह आपको मैसअप को पूर्ववत करने और फिर एप्लिकेशन को ठीक करने देता है। अगर मैं इस मुद्दे के लिए इस आदमी को 100 वोट दे सकता था जिसे मुझे अब ठीक करना था।
छिपकली

7
मैं छिपकली से सहमत हूं। यह उस स्थिति में एक बहुत ही उपयोगी समाधान था, जिसमें मुझे SHOW Engine INNODB STATUS
Travis Schneeberger

8
इस तरह से लंबे समय से चल रहे क्वेरी को कैसे मारना खतरनाक है ? कॉलिंग करने वाले ग्राहक को केवल एक त्रुटि मिलेगी।
एक्सॉनक्रॉस

7
मैं अपनी बात मिलता @EricLeschinski, लेकिन मैं पूछने के लिए क्यों दुनिया में आप की तरह एक लापरवाह डेटाबेस का उपयोग होता है MySQL एक पर जीवन-जोखिम प्रणाली?
Xeoncross

96
mysql> set innodb_lock_wait_timeout=100

Query OK, 0 rows affected (0.02 sec)

mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 100   |
+--------------------------+-------+

अब लॉक को फिर से ट्रिगर करें। आपके पास SHOW ENGINE INNODB STATUS\Gडेटाबेस जारी करने और यह देखने के लिए 100 सेकंड का समय है कि कौन सा लेनदेन आपका लॉक कर रहा है।


8
यह उत्तर यह नहीं बताता है कि पूछने वाले को उनकी त्रुटि क्यों मिल रही है। क्या आप इस बारे में विस्तार से बता सकते हैं कि सिर्फ जवाब देने के अलावा क्यों?
स्लेज

5
+1 हालांकि यह सीधे सवाल का जवाब नहीं देता है, मेरे लिए यह इस मुद्दे को हल करने के लिए एक अच्छा संदर्भ है।
जोसेफ़ हारुश

1
@ArtB dev.mysql.com/doc/innodb/1.1/en/… संक्षेप में, ओपी को त्रुटि प्राप्त हो रही है क्योंकि लेनदेन को समाप्त करने से पहले एक ताला को मेज पर बुलाया गया था और समय समाप्त होने से पहले lock_wait_timeoutमूल्य से अधिक हो गया
fyee

70

यदि आपका डेटाबेस ठीक है तो उस पर एक नज़र डालें। विशेषकर लेन-देन अलगाव। Innodb_lock_wait_timeout चर को बढ़ाने के लिए अच्छा विचार नहीं है।

Mysql cli में अपने डेटाबेस लेनदेन अलगाव स्तर की जाँच करें:

mysql> SELECT @@GLOBAL.transaction_isolation, @@transaction_isolation, @@session.transaction_isolation;
+-----------------------+-----------------+------------------------+
| @@GLOBAL.tx_isolation | @@tx_isolation  | @@session.tx_isolation |
+-----------------------+-----------------+------------------------+
| REPEATABLE-READ       | REPEATABLE-READ | REPEATABLE-READ        |
+-----------------------+-----------------+------------------------+
1 row in set (0.00 sec)

आप डी आइसोलेशन स्तर में सुधार कर सकते हैं, READATABLE READ (InnoDB Defaults) के बजाय READ COMMITTED जैसे ओरेकल का उपयोग करें।

mysql> SET tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> 

साथ ही यदि केवल निटरी में UPDATE के लिए SELECT का उपयोग करने का प्रयास करें।


1
यह लॉकिंग मुद्दों के लिए एक महान समाधान है।
रेडॉलेंट

3
मेरे लिए महान काम करता है, my.cnf संस्करण [mysqld] लेन-देन-अलगाव = READ-COMMITTED
बेनोइट गौथियर

बस एक नोट: MySQL 8 ने tx_isolationचर का नाम बदल दिया है transaction_isolation
xonya

जब आप रीड-आइसोलेशन से READ COMMITTED में बदलते हैं, तो यह जानने के लिए कि आपको क्या हो रहा है, यह जानने के लिए कार्स की मदद लेनी पड़ी। आप गंदे डेटा को समाप्त कर सकते हैं जिससे आप बचना चाहते हैं। विकिपीडिया Isoloation
Huggie

27

सुझाए गए किसी भी समाधान ने मेरे लिए काम नहीं किया लेकिन यह किया।

कुछ क्वेरी के निष्पादन को रोक रहा है। सबसे अधिक संभावना है कि आपकी क्वेरी में से किसी एक तालिका से किसी अन्य क्वेरी को अपडेट करना, सम्मिलित करना या हटाना। आपको पता लगाना है कि वह क्या है:

SHOW PROCESSLIST;

एक बार जब आप अवरुद्ध प्रक्रिया का पता लगा लेते हैं, तो उसका पता लगाएं idऔर चलाएं:

KILL {id};

अपनी प्रारंभिक क्वेरी फिर से चलाएँ।


मैं आकस्मिक रूप से SHOW PROCESSLIST के साथ सूचीबद्ध सभी प्रक्रियाओं को मार दिया; अब मुझे phpmyadmin में 500 त्रुटि मिल रही हैं। क्या वह 500 त्रुटि इन प्रक्रियाओं को मारने से संबंधित है? यदि हाँ, तो मैं इसे कैसे पुनः आरंभ कर सकता हूँ।
दशरथ

मैं देख सकता हूं कि आप क्या वर्णन करते हैं, हालांकि इस प्रक्रिया को मारने से काम नहीं चलता। प्रक्रिया 'कमांड "मारी गई" है, लेकिन यह प्रक्रिया सूची में बनी हुई है।
टॉरस्टेन

12

मार्कआर ने जो कहा, उसके साथ 100%। ऑटोकॉमिट प्रत्येक स्टेटमेंट को एक स्टेटमेंट ट्रांजेक्शन बनाता है।

SHOW ENGINE INNODB STATUSगतिरोध के कारण आपको कुछ सुराग देना चाहिए। अपनी धीमी क्वेरी लॉग पर एक अच्छी नज़र रखें और यह देखने के लिए कि तालिका क्या और क्या कर रही है और जो कुछ भी पूर्ण टेबलस्कैन कर रहा है उसे दूर करने का प्रयास करें। पंक्ति स्तर लॉकिंग अच्छी तरह से काम करती है लेकिन तब नहीं जब आप सभी पंक्तियों को लॉक करने का प्रयास कर रहे हों!


5

क्या आप इस तालिका के भीतर किसी अन्य रिकॉर्ड को अपडेट कर सकते हैं, या क्या यह तालिका भारी उपयोग की गई है? मैं जो सोच रहा हूं, वह यह है कि जब वह लॉक को प्राप्त करने का प्रयास कर रहा है, तो उसे इस रिकॉर्ड को अपडेट करने की आवश्यकता है जो कि टाइमआउट सेट किया गया था। आप उस समय को बढ़ाने में सक्षम हो सकते हैं जो मदद कर सकता है।


3
शायद innodb_lock_wait_timeoutमेंmy.cnf
Oblig

1
मैंने my.cnf में सेट किया: <br/> innodb_lock_wait_timeout = 120 <br/> डिफ़ॉल्ट mysql 5.5 के लिए 50 है। इस परिवर्तन के बाद मैं इस मुद्दे को अपनी इकाई परीक्षणों में नहीं देख पा रहा था! प्रोक्सूल से टॉमकैट जेडबीबीसी पूल में स्विच करने के बाद ऐसा हुआ। संभवत: टॉमकट पूल के साथ अधिक लेनदेन के समय के कारण ?!
Champ

3

पंक्तियों की संख्या बहुत बड़ी नहीं है ... अगर प्राथमिक कुंजी नहीं है तो account_import_id पर एक इंडेक्स बनाएं।

CREATE INDEX idx_customer_account_import_id ON customer (account_import_id);

OMG ... इसने मुझे बचा लिया। मैंने एक सूचकांक को गिराकर उत्पादन डीबी को खराब कर दिया है और इसे ठीक कर दिया है। आपका धन्यवाद।
निक गॉटेक

2

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

विवरण:

मैंने लगभग 1 मिलियन पंक्तियों में से लगभग 900,000 निकालने के लिए एक DELETE क्वेरी जारी की थी।

मैंने इसे गलती से चलाया (केवल 10% पंक्तियों को हटा दिया): DELETE FROM table WHERE MOD(id,10) = 0

इसके बजाय (90% पंक्तियों को निकालता है): DELETE FROM table WHERE MOD(id,10) != 0

मैं 90% पंक्तियों को निकालना चाहता था, 10% को नहीं। इसलिए मैंने MySQL कमांड लाइन में प्रक्रिया को मार डाला, यह जानते हुए कि यह अब तक हटाए गए सभी पंक्तियों को वापस करेगा।

फिर मैंने तुरंत सही कमांड चलाई, और इसके तुरंत lock timeout exceededबाद एक त्रुटि हुई। मुझे एहसास हुआ कि ताला वास्तव rollbackमें पृष्ठभूमि में अभी भी मारे गए क्वेरी का हो सकता है। इसलिए मैंने कुछ सेकंड इंतजार किया और क्वेरी को फिर से चलाया।


1

सुनिश्चित करें कि डेटाबेस टेबल InnoDB भंडारण इंजन और READ-COMMITTED लेनदेन अलगाव स्तर का उपयोग कर रहे हैं।

आप इसे SELECT @@ GLOBAL.tx_isolation, @@ tx_isolation करके देख सकते हैं; mysql कंसोल पर।

अगर यह READ-COMMITTED होना तय नहीं है तो आपको इसे सेट करना होगा। यह सुनिश्चित करने से पहले सुनिश्चित करें कि आपके पास mysql में SUPER विशेषाधिकार हैं।

आप http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html से मदद ले सकते हैं ।

इसे स्थापित करने से मुझे लगता है कि आपकी समस्या हल हो जाएगी।


आप एक बार में दो प्रक्रियाओं में इसे अपडेट करने का प्रयास नहीं कर सकते हैं। उपयोगकर्ताओं (@tala) को इस संदर्भ में इसी तरह के त्रुटि संदेशों का सामना करना पड़ा है, हो सकता है कि डबल-चेक करें ...


1

मैं Google से आया था और मैं सिर्फ उस समाधान को जोड़ना चाहता था जो मेरे लिए काम करता है। मेरी समस्या यह थी कि मैं एक विशाल तालिका के रिकॉर्ड को हटाने की कोशिश कर रहा था जिसमें कैस्केड में बहुत अधिक एफके था इसलिए मुझे ओपी के समान त्रुटि मिली।

मैंने अक्षम कर दिया autocommitऔर फिर COMMITSQL वाक्य के अंत में इसे जोड़ने का काम किया । जहाँ तक मैं समझता था कि यह कमांड के अंत में प्रतीक्षा करने के बजाय बफर बिट को थोड़ा सा रिलीज करता है।

ओपी के उदाहरण के साथ रखने के लिए, यह काम करना चाहिए:

mysql> set autocommit=0;

mysql> update customer set account_import_id = 1; commit;

autocommitयदि आप पहले की तरह MySQL config को छोड़ना चाहते हैं तो फिर से पुनः सक्रिय करना न भूलें ।

mysql> set autocommit=1;


0

पार्टी के लिए देर से (हमेशा की तरह) हालांकि मेरा मुद्दा यह था कि मैंने कुछ खराब एसक्यूएल (एक नौसिखिया) लिखा था और कई प्रक्रियाओं में रिकॉर्ड (एस) पर ताला लगा था - निश्चित रूप से उपयुक्त क्रिया नहीं। मैंने समाप्त कर दिया है: SHOW PROCESSLISTऔर फिर आईडी का उपयोग करके मारनाKILL <id>


0

इस तरह की बात मुझे तब हुई जब मैं php भाषा निर्माण निकास का उपयोग कर रहा था; लेन-देन के बीच में। फिर यह लेन-देन "हैंग" होता है और आपको mysql प्रक्रिया को मारने की जरूरत है (प्रक्रिया सूची के साथ ऊपर वर्णित है;)


0

मेरे उदाहरण में, मैं डेटा को ठीक करने के लिए एक असामान्य क्वेरी चला रहा था। यदि आप अपनी क्वेरी में तालिकाओं को लॉक करते हैं, तो आपको लॉक टाइमआउट से निपटना नहीं होगा:

LOCK TABLES `customer` WRITE;
update customer set account_import_id = 1;
UNLOCK TABLES;

यह शायद सामान्य उपयोग के लिए एक अच्छा विचार नहीं है।

अधिक जानकारी के लिए देखें: MySQL 8.0 संदर्भ मैनुअल


0

मैं 2 डॉक्ट्रीन डीबीएएल कनेक्शनों में भाग गया, उनमें से एक गैर-लेन-देन के रूप में (महत्वपूर्ण लॉग के लिए), वे एक दूसरे पर निर्भर नहीं करते हुए समानांतर चलने का इरादा रखते हैं।

CodeExecution(
    TransactionConnectionQuery()
    TransactionlessConnectionQuery()
)

बहुत परीक्षण के बाद डेटा रोलबैक के लिए मेरे एकीकरण परीक्षणों को लेनदेन में लपेटा गया।

beginTransaction()
CodeExecution(
    TransactionConnectionQuery()
    TransactionlessConnectionQuery() // CONFLICT
)
rollBack()

मेरा समाधान उन परीक्षणों में रैपिंग लेनदेन को अक्षम करना था और डीबी डेटा को दूसरे तरीके से रीसेट करना था।


-4

यह एक ही त्रुटि थी, भले ही मैं केवल एक प्रविष्टि के साथ एक तालिका अपडेट कर रहा था, लेकिन mysql को पुनरारंभ करने के बाद, इसे हल किया गया था।

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