गतिरोध के कारण SqlException को कैसे पकड़ा जाए?


92

.NET 3.5 / C # ऐप से, मैं तभी पकड़ना चाहूंगा SqlExceptionलेकिन अगर यह SQL Server 2008 के उदाहरण पर गतिरोध के कारण होता है

विशिष्ट त्रुटि संदेश है Transaction (Process ID 58) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

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

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


3
मैंने (अंत में) त्रुटि कोड के लिए प्रलेखन पाया: msdn.microsoft.com/en-us/library/aa337376.aspx । आप इसे SQL सर्वर के माध्यम से भी पा सकते हैं:select * from master.dbo.sysmessages where error=1205
मार्टिन मैकएनकेयर

जवाबों:


153

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

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

या, C # 6 में उपलब्ध अपवाद फ़िल्टरिंग का उपयोग करना

catch (SqlException ex) when (ex.Number == 1205)
{
    // Deadlock 
}

किसी दिए गए संदेश के लिए वास्तविक SQL त्रुटि कोड को खोजने के लिए एक आसान बात है, SQL सर्वर में sys.messages में देखना।

जैसे

SELECT * FROM sys.messages WHERE text LIKE '%deadlock%' AND language_id=1033

डेडलॉक को संभालने के लिए एक वैकल्पिक तरीका (SQL सर्वर 2005 और उसके बाद से), इसे TRY ... CATT समर्थन का उपयोग करके संग्रहीत कार्यविधि के भीतर करना है:

BEGIN TRY
    -- some sql statements
END TRY
BEGIN CATCH
    IF (ERROR_NUMBER() = 1205)
        -- is a deadlock
    ELSE
        -- is not a deadlock
END CATCH

MSDN में एक पूर्ण उदाहरण यहाँ है कि SQL के भीतर विशुद्ध रूप से गतिरोध तर्क को कैसे लागू किया जाए।


2
ध्यान दें कि त्रुटि कोड विक्रेता विशिष्ट हैं, इसलिए 1205 SQL सर्वर के लिए एक गतिरोध है, लेकिन यह Oracle, MySQL, आदि के लिए भिन्न हो सकता है
ब्रायनमर्न्स

3
डेटा लेयर के आधार पर, SqlExceptionएक दूसरे में लपेटा जा सकता है। इसलिए हमें किसी भी अपवाद प्रकार को पकड़ने और फिर उन्हें जांचने की आवश्यकता हो सकती है, यदि वे सीधे गतिरोध अपवाद नहीं हैं, तो पुन: जाँच करें InnerException
फ्रैडरिक

46

क्योंकि मुझे लगता है कि आप संभवतः गतिरोधों का पता लगाना चाहते हैं, विफल ऑपरेशन को फिर से करने में सक्षम होने के लिए, मैं आपको थोड़ा गेटा के लिए चेतावनी देना पसंद करता हूं। मुझे आशा है कि आप यहाँ विषय से थोड़ा हटकर होंगे।

डेटाबेस द्वारा पाया गया एक गतिरोध प्रभावी रूप से उस लेनदेन को रोलबैक करेगा जिसमें आप चला रहे थे (यदि कोई हो), जबकि कनेक्शन को .NET में खुला रखा गया हो। उस ऑपरेशन (उसी कनेक्शन में) को फिर से करना, इसका मतलब यह है कि इसे लेनदेन रहित संदर्भ में निष्पादित किया जाएगा और इससे डेटा भ्रष्टाचार हो सकता है।

इसके लिए जागरूक होना जरूरी है। SQL द्वारा पूर्ण विफलता के कारण पूर्ण कनेक्शन पर विचार करना सबसे अच्छा है। ऑपरेशन को फिर से करना केवल उस स्तर पर किया जा सकता है जहां लेनदेन को परिभाषित किया गया है (उस लेनदेन और इसके कनेक्शन को पुन: बनाकर)।

इसलिए जब आप एक असफल ऑपरेशन को पुनः प्रयास कर रहे हैं, तो कृपया सुनिश्चित करें कि आपने पूरी तरह से नया कनेक्शन खोल दिया है और एक नया लेनदेन शुरू कर रहे हैं।


4
आपको पूरी तरह से नए कनेक्शन की आवश्यकता क्यों है? मैंने इस उत्तर के बारे में एक प्रश्न यहाँ पोस्ट किया है
सैम

3

यहां गतिरोधों का पता लगाने का C # 6 तरीका है।

try
{
    //todo: Execute SQL. 
    //IMPORTANT, if you used Connection.BeginTransaction(), this try..catch must surround that code. You must rollback the original transaction, then recreate it and re-run all the code.
}
catch (SqlException ex) when (ex.Number == 1205)
{
    //todo: Retry SQL
}

सुनिश्चित करें कि यह प्रयास करें..अपने पूरे लेनदेन को घेर लें। @Steven के अनुसार (विवरण के लिए उसका उत्तर देखें), जब गतिरोध के कारण sql कमांड विफल हो जाती है, तो यह लेन-देन को पीछे ले जाने का कारण बनता है और, यदि आप लेन-देन को फिर से नहीं बनाते हैं, तो आपका पुनः प्रयास संदर्भ के बाहर निष्पादित होगा लेनदेन और डेटा विसंगतियों में परिणाम कर सकते हैं।

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