गतिरोध के मुख्य कारण क्या हैं और क्या उन्हें रोका जा सकता है?


55

हाल ही में हमारे ASP.NET अनुप्रयोगों में से एक ने डेटाबेस डेडलॉक त्रुटि प्रदर्शित की और मुझे त्रुटि की जांच करने और ठीक करने का अनुरोध किया गया। मैं गतिरोध का कारण खोजने में कामयाब रहा, एक संग्रहीत प्रक्रिया थी जो कड़ाई से एक कर्सर के भीतर एक तालिका को अपडेट कर रही थी।

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

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

मुझे खुशी हुई और मैं अपने प्रोजेक्ट पर वापस आ गया, और उस गतिरोध का कारण जानने के लिए कुछ शोध किया ...

जाहिर है, यह एक परिपत्र प्रतीक्षा स्थिति थी जो गतिरोध का कारण बनी। अपडेट प्राथमिक रूप से प्राथमिक कुंजी की तुलना में प्राथमिक कुंजी के बिना अधिक समय लेता है।

मुझे पता है कि यह एक अच्छी तरह से परिभाषित निष्कर्ष नहीं है, यही कारण है कि मैं यहां पोस्ट कर रहा हूं ...

  • क्या लापता प्राथमिक समस्या है?
  • क्या कोई अन्य शर्तें हैं जो गतिरोध के अलावा अन्य कारण हैं (आपसी बहिष्कार, पकड़ और प्रतीक्षा, कोई पूर्व भुगतान और परिपत्र प्रतीक्षा)?
  • मैं गतिरोध को कैसे रोकूं और ट्रैक करूं?

2
आईएमई बहुमत (सभी!) गतिरोधों के कारण मैंने देखा है कि परिपत्र प्रतीक्षा (मुख्य रूप से ट्रिगर के अत्यधिक उपयोग के कारण)।
सत्यजित भट

गतिरोध एक गतिरोध की आवश्यक शर्तों में से एक है। यदि आपके सभी सत्र एक ही क्रम में ताले प्राप्त करते हैं, तो आप किसी भी गतिरोध से बच सकते हैं।
पीटर जी।

जवाबों:


38

गतिरोध को ट्रैक करना दो में से आसान है:

डिफ़ॉल्ट रूप से, त्रुटि लॉग में गतिरोध नहीं लिखे गए हैं। आप SQL को ट्रेस झंडे 1204 और 3605 के साथ त्रुटि लॉग में लिखने का कारण बन सकते हैं।

SQL सर्वर त्रुटि लॉग के लिए डेडलॉक जानकारी लिखें: DBCC TRACEON (-1, 1204, 3605)

इसे बंद करें: DBCC TRACEOFF (-1, 1204, 3605)

ट्रेस फ्लैग 1204 और आउटपुट के चालू होने की चर्चा के लिए "समस्या निवारण डेडलॉक" देखें। https://msdn.microsoft.com/en-us/library/ms178104.aspx

रोकथाम अधिक कठिन है, अनिवार्य रूप से आपको निम्नलिखित के लिए बाहर देखना होगा:

उस क्रम में कोड ब्लॉक 1 संसाधन A, फिर संसाधन B को लॉक करता है।

उस क्रम में कोड ब्लॉक 2 संसाधन बी को लॉक करता है, फिर संसाधन ए।

यह क्लासिक स्थिति है जहां एक गतिरोध हो सकता है, अगर दोनों संसाधनों का ताला परमाणु नहीं है, तो कोड ब्लॉक 1 ए को लॉक कर सकता है और पूर्व खाली किया जा सकता है, फिर कोड ब्लॉक 2 लॉक बी से पहले ए को प्रसंस्करण समय वापस मिलता है। अब आपके पास गतिरोध है।

इस स्थिति को रोकने के लिए, आप निम्न की तरह कुछ कर सकते हैं

कोड ब्लॉक A (पेसो कोड)

Lock Shared Resource Z
    Lock Resource A
    Lock Resource B
Unlock Shared Resource Z
...

कोड ब्लॉक B (छद्म कोड)

Lock Shared Resource Z
    Lock Resource B
    Lock Resource A
Unlock Shared Resource Z
...

जब उनके साथ ए और बी को अनलॉक करना न भूलें

इससे कोड ब्लॉक A और कोड ब्लॉक B के बीच गतिरोध को रोका जा सकेगा

डेटाबेस के नजरिए से, मुझे यकीन नहीं है कि इस स्थिति को रोकने के बारे में कैसे जाना जा सकता है, क्योंकि डेटा को अपडेट करते समय डेटाबेस को स्वयं ही हैंडल किया जाता है, अर्थात पंक्ति / टेबल लॉक। जहाँ मैंने सबसे अधिक समस्याएँ देखीं, जहाँ आपने अपना देखा, एक कर्सर के अंदर। कर्सर कुख्यात अक्षम हैं, यदि संभव हो तो उनसे बचें।


क्या आपका मतलब कोड ब्लॉक B में संसाधन B से पहले संसाधन A को लॉक करना था? जैसा कि लिखा गया है, यह गतिरोध का कारण बनेगा .. जैसा कि आप पहले टिप्पणियों में उल्लेख कर चुके हैं। जितना संभव हो, आप हमेशा उसी क्रम में संसाधनों को लॉक करना चाहते हैं, भले ही आपको लॉकिंग के उस आदेश को सुनिश्चित करने के लिए शुरुआत में डमी प्रश्नों की आवश्यकता हो।
जेरार्ड ओनेल

23

डेडलॉक के बारे में पढ़ने और जानने के लिए मेरे पसंदीदा लेख हैं: सरल टॉक - डेडलॉक और एसक्यूएल सर्वर सेंट्रल को ट्रैक करें - डेडलॉक को हल करने के लिए प्रोइलर का उपयोग करना । वे आपको एक स्थिति चूसने के तरीके के बारे में नमूने और सलाह देंगे।

संक्षेप में, एक मौजूदा समस्या को हल करने के लिए, मैं लेन-देन को कमतर बनाऊंगा, अनावश्यक भाग को उनमें से निकाल दूंगा, वस्तुओं के उपयोग के आदेश का ध्यान रखूंगा, देखिए कि वास्तव में अलगाव स्तर की आवश्यकता है, अनावश्यक नहीं पढ़ें डेटा...

लेकिन लेखों को बेहतर ढंग से पढ़ें, वे सलाह देने के तरीके में अच्छे होंगे।


16

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

उदाहरण के लिए, InnoDB में :

यदि आपके पास अपने बयान के लिए उपयुक्त कोई अनुक्रमणिका नहीं है और MySQL को कथन को संसाधित करने के लिए पूरी तालिका को स्कैन करना होगा, तो तालिका की प्रत्येक पंक्ति लॉक हो जाती है, जो बदले में अन्य उपयोगकर्ताओं द्वारा तालिका में सभी आवेषण को अवरुद्ध करती है। अच्छे सूचकांक बनाना महत्वपूर्ण है ताकि आपके प्रश्न अनावश्यक रूप से कई पंक्तियों को स्कैन न करें।

एक अन्य आम उपाय यह है कि जब जरूरत न हो तब लेन-देन की निरंतरता को बंद कर दें, या अन्यथा अपने अलगाव के स्तर को बदल दें , उदाहरण के लिए, आँकड़ों की गणना करने के लिए एक लंबे समय तक चलने वाला काम ... एक करीबी उत्तर आमतौर पर पर्याप्त है, आपको सटीक संख्याओं की आवश्यकता नहीं है, जैसा कि वे आपके नीचे से बदल रहे हैं। और अगर इसे पूरा करने में 30 मिनट लगते हैं, तो आप नहीं चाहते कि यह उन तालिकाओं पर अन्य सभी लेनदेन को रोक दे।

...

उन्हें ट्रैक करने के लिए, यह आपके द्वारा उपयोग किए जा रहे डेटाबेस सॉफ़्टवेयर पर निर्भर करता है।


डाउनवोटिंग करते समय टिप्पणियां प्रदान करना आम बात है ... यह एक वैध उत्तर है, टेबल लॉक में अपग्रेड करने और हमेशा के लिए लेने का चयन करने वाला बयान निश्चित रूप से गतिरोध का कारण बन सकता है।
ब्लैकिस

1
यदि अनुक्रमणिका को क्लस्टर नहीं किया जाता है, तो MS SQLServer अप्रत्याशित लॉकिंग व्यवहार भी दे सकता है। यह पंक्ति स्तर लॉकिंग का उपयोग करने के लिए आपकी दिशा को चुपचाप अनदेखा करेगा और पृष्ठ स्तर लॉकिंग करेगा। फिर आप पृष्ठ पर प्रतीक्षा गतिरोध प्राप्त कर सकते हैं।
Jay

7

बस कर्सर चीज़ पर विकसित करने के लिए। यह वास्तव में बहुत बुरा है। यह पूरी तालिका को बंद कर देता है फिर पंक्तियों को एक-एक करके संसाधित करता है।

थोड़ी देर के लूप का उपयोग करके कर्सर के फैशन में पंक्तियों के माध्यम से जाना सबसे अच्छा है

लूप में, लूप में प्रत्येक पंक्तियों के लिए एक चयन किया जाएगा और लॉक उस समय केवल एक पंक्ति में होगा। तालिका में डेटा का शेष भाग क्वेरी करने के लिए स्वतंत्र है, जिससे गतिरोध होने की संभावना कम हो जाती है।

इसके अलावा यह तेज है। आपको आश्चर्य होता है कि वैसे भी शाप देने वाले क्यों होते हैं।

यहाँ इस तरह की संरचना का एक उदाहरण दिया गया है:

DECLARE @LastID INT = (SELECT MAX(ID) FROM Tbl)
DECLARE @ID     INT = (SELECT MIN(ID) FROM Tbl)
WHILE @ID <= @LastID
    BEGIN
    IF EXISTS (SELECT * FROM Tbl WHERE ID = @ID)
        BEGIN
        -- Do something to this row of the table
        END

    SET @ID += 1  -- Don't forget this part!
    END

यदि आपका आईडी क्षेत्र विरल है, तो आप आईडी की एक अलग सूची खींचना चाहते हैं और उसके माध्यम से पुनरावृति कर सकते हैं:

DECLARE @IDs TABLE
    (
    Seq INT NOT NULL IDENTITY PRIMARY KEY,
    ID  INT NOT NULL
    )
INSERT INTO @IDs (ID)
    SELECT ID
    FROM Tbl
    WHERE 1=1  -- Criteria here

DECLARE @Rec     INT = 1
DECLARE @NumRecs INT = (SELECT MAX(Seq) FROM @IDs)
DECLARE @ID      INT
WHILE @Rec <= @NumRecs
    BEGIN
    SET @ID = (SELECT ID FROM @IDs WHERE Seq = @Seq)

    -- Do something to this row of the table

    SET @Seq += 1  -- Don't forget this part!
    END

6

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

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

मेरी पसंदीदा लॉक रोकथाम रणनीति 'स्नैपशॉट' सुविधाओं का उपयोग कर रही है। रीड कमिटेड स्नैपशॉट फीचर का मतलब है कि रीड ताले का उपयोग नहीं करता है! और अगर आपको 'Read प्रतिबद्ध' की तुलना में अधिक नियंत्रण की आवश्यकता है, तो 'स्नैप शॉट आइसोलेशन स्तर' सुविधा है। यह एक क्रमबद्ध (एमएस शर्तों का उपयोग करके) लेनदेन की अनुमति देता है जबकि अन्य खिलाड़ियों को अवरुद्ध नहीं करता है।

अंत में, अपडेट लॉक का उपयोग करके गतिरोध के एक वर्ग को रोका जा सकता है। यदि आप रीड पढ़ते हैं (होल्ड करते हैं, या रिपीटेबल रीड का उपयोग करते हैं), और दूसरी प्रक्रिया भी ऐसा ही करती है, तो दोनों एक ही रिकॉर्ड को अपडेट करने का प्रयास करते हैं, आपके पास एक गतिरोध होगा। लेकिन अगर दोनों एक अपडेट लॉक का अनुरोध करते हैं, तो दूसरी प्रक्रिया पहले की प्रतीक्षा करेगी, जबकि अन्य प्रक्रियाओं को साझा लॉक का उपयोग करके डेटा को पढ़ने की अनुमति है जब तक कि डेटा वास्तव में लिखा नहीं जाता है। यह निश्चित रूप से काम नहीं करेगा यदि कोई प्रक्रिया अभी भी साझा होल्ड लॉक का अनुरोध करती है।


-2

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

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