2010-05-31 11 views
5

मेरे पास एएसपी.नेट एमवीसी/एसक्यूएल सर्वर में एक बहुत ही लोकप्रिय साइट है, और दुर्भाग्य से बहुत सारे डेडलॉक्स होते हैं। जबकि मैं यह पता लगाने की कोशिश कर रहा हूं कि वे एसक्यूएल प्रोफाइलर के माध्यम से क्यों होते हैं, मुझे आश्चर्य है कि मैं डेडलॉक्स करते समय SQL सर्वर का डिफ़ॉल्ट व्यवहार कैसे बदल सकता हूं।स्वचालित रूप से डेडलॉक लेनदेन को फिर से चलाने के लिए कैसे करें? (एएसपी.नेट एमवीसी/एसक्यूएल सर्वर)

क्या लेनदेन को फिर से चलाने के लिए संभव है जिससे त्रुटि स्क्रीन दिखाने की बजाय समस्याएं उत्पन्न हुईं?

उत्तर

6

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

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

तुम भी स्नैपशॉट अलगाव उपयोग करने पर विचार हो सकता है, ताला मुक्त के बाद से:

वहाँ कई, कई संसाधनों वहाँ बाहर कैसे पहचान करने और गतिरोध को हल करने पर हैं स्नैपशॉट में शामिल पढ़ता है उस सतह को कम करता है जिस पर डेडलॉक्स हो सकते हैं (यानी केवल लिखने-लिखने वाले डेडलॉक्स हो सकते हैं)। Using Row Versioning-based Isolation Levels देखें।

+0

@ मिच: किसी भी पुनः प्रयास तर्क * आवेदन * में होना होगा। मेरा मुद्दा यह है कि आप SQL सर्वर को अपने लेनदेन को रिकॉर्ड नहीं कर सकते हैं और इसे आपके लिए पुनः प्रयास कर सकते हैं। –

2

अक्सर होने वाले कई डेडलॉक्स अक्सर संकेत देते हैं कि आपके पास सही इंडेक्स नहीं हैं और/या आपके आंकड़े पुराने हैं। क्या आपके पास रखरखाव के हिस्से के रूप में नियमित अनुसूचित इंडेक्स पुनर्निर्माण है?

आपकी सहेजने वाली कोड स्वचालित रूप से सहेजनी चाहिए जब त्रुटि 1205 लौटा दी जाती है (डेडलॉक हुआ)। एक मानक पैटर्न है जो इस तरह दिखता है:

catch (SqlException ex) 
{ 
    if (ex.Number == 1205) 
    { 
     // Handle Deadlock by retrying save... 
    } 
    else 
    { 
     throw; 
    } 
} 

दूसरा विकल्प आपकी संग्रहीत प्रक्रियाओं में पुनः प्रयास करना है। इसका एक उदाहरण यहां दिया गया है: Using TRY...CATCH in Transact-SQL

+0

हाँ, मुझे पता है: मेरे तर्क में एक गड़बड़ होनी चाहिए। लेकिन सवाल यह है कि मैं सर्वर के व्यवहार को कैसे बदल सकता हूं? – Alex

+1

वह नहीं कह रहा है कि आपका कोड खराब है। वह कह रहा है कि आपको डेटाबेस में अपनी टेबल पर इंडेक्स की समीक्षा करनी चाहिए, या फिर उन्हें फिर से बनाना या नए जोड़ना चाहिए। –

+0

ठीक है ... फिर एक और सवाल। आइए मान लें कि पेज ए पर डेडलॉक होता है, लेकिन पेज बी लॉक किए गए डेटा तक पहुंचने का प्रयास कर रहा है। त्रुटि पेज बी पर प्रदर्शित की जाएगी, लेकिन इसका मतलब यह नहीं है कि पृष्ठ बी पर डेडलॉक हुआ। यह अभी भी पृष्ठ ए क्षमा करें अगर यह बेवकूफ है, तो यह अवधारणा को समझना मेरे लिए वास्तव में कठिन है। – Alex

1

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

मिच का जवाब देने के लिए टिप्पणी में अपने उदाहरण को देखते:

मान लीजिए कि गतिरोध पेज ए, पर होता है लेकिन पेज बी बंद कर दिया डेटा का उपयोग करने की कोशिश कर रहा है। त्रुटि पृष्ठ बी पर प्रदर्शित होगी, लेकिन यह का अर्थ यह नहीं है कि पृष्ठ बी पर डेडलॉक हुआ।यह अभी भी पेज ए

को हुई आप लगातार देखते हैं तो गतिरोध पेज एक और पेज बी से जारी किए गए प्रश्नों से उत्पन्न, आप जो पेज एक त्रुटि में और जो परिणाम को सफलतापूर्वक पूरा प्रभावित कर सकते हैं। जैसा कि अन्य ने कहा है, आप स्वचालित रूप से पुनः प्रयास नहीं कर सकते हैं।

समस्या प्रश्नों और/या डेडलॉक ट्रेस आउटपुट के साथ एक प्रश्न पोस्ट करें और यह एक अच्छा मौका है कि आपको यह क्यों समझा जाएगा कि यह क्यों हो रहा है और इसे कैसे ठीक किया जा सकता है।

+0

धन्यवाद। समस्या यह है कि एक संग्रहित प्रक्रिया में डेडलॉक होता है। एसक्यूएल प्रोफाइलर उस प्रक्रिया का नाम दिखाता है, लेकिन मुझे यह क्वेरी नहीं मिल सकती है जहां यह होता है, और वहां बहुत सारे प्रश्न हैं। समस्या का सामना करने में मैं कैसे ट्रैक कर सकता हूं? – Alex

+1

आप ट्रेस ध्वज 1204 और 1222 को सक्षम कर सकते हैं, जिनमें से दोनों "डिटेक्टिंग एंड डेडलॉक्स" आलेख रीमस से जुड़े हुए हैं। इससे आपको प्रश्नों और कौन से संसाधनों का ब्योरा मिलेगा। पंक्तियों, पृष्ठों, अनुक्रमणिका या तालिकाओं को शामिल किया गया है और प्रत्येक प्रक्रिया द्वारा आवश्यक लॉक के प्रकार की सूचना दी जाएगी। इससे, आप एक फिक्स निर्धारित करने में सक्षम हो सकते हैं, अन्यथा डेडलॉक ट्रेस और डेडलॉकिंग प्रक्रियाओं के स्रोत के साथ एक प्रश्न पोस्ट करें। क्या आप संग्रहीत प्रक्रियाओं को संशोधित करने में असमर्थ हैं जहां समस्या होती है? –

+0

नहीं, मैं एसपी को संशोधित कर सकता हूं। मैं लेख देखता हूं, और झंडे को सक्षम करता हूं। उम्मीद है कि यह काम करेगा। – Alex

10

Remus's answer मूल रूप से त्रुटिपूर्ण है। https://stackoverflow.com/a/112256/14731 के मुताबिक एक सतत लॉकिंग ऑर्डर डेडलॉक्स को रोकता नहीं है। सबसे अच्छा हम अपनी आवृत्ति को कम कर सकते हैं।

वह दो अंक पर गलत है:

  1. निहितार्थ यह है कि गतिरोध रोका जा सकता है। आप डेडलॉक्स की आवृत्ति को कम करने के बारे में माइक्रोसॉफ्ट और आईबीएम पोस्ट लेख दोनों पाएंगे। वे कहां दावा करते हैं कि आप उन्हें पूरी तरह से रोक सकते हैं।
  2. यह संकेत कि सभी डेडलॉक्स के लिए आपको राज्य का पुनर्मूल्यांकन करने और एक नए निर्णय लेने की आवश्यकता है। आवेदन स्तर पर कुछ कार्रवाइयों को पुनः प्रयास करने के लिए यह बिल्कुल सही है, जब तक कि आप निर्णय बिंदु तक काफी दूर यात्रा करते हैं।

साइड-टिप्पणी: Remus के मुख्य मुद्दा यह है कि डेटाबेस स्वचालित रूप से आपकी ओर से कार्रवाई का पुनः प्रयास नहीं कर सकता है, और वह पूरी तरह से है कि गिनती पर सही है। लेकिन इसका मतलब यह नहीं है कि पुन: चलने वाले ऑपरेशन डेडलॉक के लिए गलत प्रतिक्रिया है।

0

कुछ मामलों में, आप नीचे कर सकते हैं। शुरूआत ट्रैन और प्रतिबद्धता के बीच सब कुछ या कुछ भी नहीं है। तो या तो @errorcode 0 मान के रूप में लेता है और लूप समाप्त होता है, या, विफलता के मामले में, 1 से काउंटर कम करें और पुनः प्रयास करें। यह काम नहीं कर सकता है अगर आप बाहरी शुरू ट्रैन/प्रतिबद्ध से कोड को चर प्रदान करते हैं। बस एक विचार :)

declare @errorcount int = 4 -- retry number 
while @errorcount >0 
begin 
begin tran 
<your code here> 
set @errorcount =0 
commit 
set @[email protected] 
end 
संबंधित मुद्दे