SQL 2005 संग्रहीत procs में त्रुटि हैंडलिंग को जोड़ने के लिए सबसे अच्छा तरीका क्या है?


11

स्टोर किए गए प्रॉक्स को मजबूत बनाने का एक अच्छा तरीका क्या है कि वे बहुत अच्छी तरह से स्केल कर सकें और एरर हैंडलिंग भी हो?

इसके अतिरिक्त, एक संग्रहीत खरीद में कई त्रुटि परिदृश्यों को संभालने का सबसे अच्छा तरीका क्या है और एक बुद्धिमान प्रतिक्रिया प्रणाली है जो कॉलिंग एप्लिकेशन को सार्थक त्रुटि जानकारी लौटाएगी?


2
SQL Server 2005 में नए TRY CATCH ब्लॉक का उपयोग करने का प्रयास करें। sommarskog.se/error_handling_2005.html
Sankar Reddy

Hi @Kacalapy ~ मैं भविष्य में अपने आप में प्रत्येक प्रश्न पूछने के लिए सिफारिश करना चाहता हूं और इस तरह हम एक समय में एक प्रश्न पर केंद्रित विशिष्ट उत्तर दे सकते हैं। मैं आपको इस सवाल के साथ करने के लिए प्रोत्साहित करता हूं।
jcolebrand

जवाबों:


12

एलेक्स कुजनेत्सोव ने अपनी पुस्तक डिफेंसिव डेटाबेस प्रोग्रामिंग (चैप्टर 8) में एक महान अध्याय है जिसमें टी-एसक्यूएल टीआरवाई ... कैटच, टी-एसक्यूएल लेनदेन और सेट एक्सएक्ट_एबेट सेटिंग्स, और क्लाइंट साइड एरर हैंडलिंग का उपयोग किया गया है। यह निर्णय लेने में आपको बहुत मदद करेगा कि आपको किन विकल्पों को पूरा करने की आवश्यकता है।

यह इस साइट पर मुफ्त में उपलब्ध है । मैं कंपनी के साथ किसी भी तरह से संबद्ध नहीं हूं, लेकिन मैं उस पुस्तक के हार्ड कॉपी संस्करण का मालिक हूं।

इस विषय पर बहुत कम विवरण हैं जो एलेक्स द्वारा बहुत अच्छी तरह से समझाया गया है।

निक के अनुरोध के अनुसार ... (लेकिन यह सब अध्याय में नहीं है)

स्केलिंग के संदर्भ में, आपको क्रूरतापूर्वक ईमानदार होने की आवश्यकता है कि कौन सी गतिविधियाँ db कोड में होनी चाहिए और कौन सी ऐप में होनी चाहिए। कभी ध्यान दें कि फास्ट-एक्ज़ीक्यूटिंग कोड प्रति विधि एकल चिंता के लिए डिजाइनिंग में वापस कैसे आता है?

संवाद करने का सबसे आसान तरीका कस्टम त्रुटि कोड (> 50,000) होगा। यह भी बहुत तेज है। इसका मतलब है कि आपको db कोड और ऐप कोड को सिंक में रखना होगा। कस्टम त्रुटि कोड के साथ, आप त्रुटि संदेश स्ट्रिंग में उपयोगी जानकारी भी वापस कर सकते हैं। क्योंकि उस स्थिति के लिए आपके पास एक त्रुटि कोड सख्ती से है, तो आप त्रुटि के डेटा प्रारूप के अनुरूप ऐप कोड में एक पार्सर लिख सकते हैं।

इसके अलावा, डेटाबेस में कौन से त्रुटि की स्थिति को पुन: प्रयास करने की आवश्यकता है? यदि आप X सेकंड के बाद पुन: प्रयास करना चाहते हैं, तो आप ऐप कोड में संभालना बेहतर समझते हैं ताकि लेन-देन अधिक से अधिक ब्लॉक न हो। यदि आप अभी तुरंत DML ऑपरेशन को फिर से सबमिट कर रहे हैं, तो इसे SP में दोहराना अधिक कुशल हो सकता है। हालांकि, ध्यान रखें कि आपको संभवतः एक कोड को पूरा करने के लिए कोड को डुप्लिकेट करना होगा या एसपी की एक परत जोड़ना होगा।

वास्तव में, यह वर्तमान में TRY के साथ सबसे बड़ा दर्द है ... फिलहाल SQL सर्वर में CATCH तर्क। यह किया जा सकता है, लेकिन यह थोड़ा सा है। SQL सर्वर 2012 में इसमें आने वाले कुछ सुधारों को देखें, विशेष रूप से सिस्टम अपवादों को फिर से फेंकना (मूल त्रुटि संख्या को संरक्षित करना)। इसके अलावा, FORMATMESSAGE है , जो त्रुटि संदेशों के निर्माण में कुछ लचीलापन जोड़ता है, विशेष रूप से लॉगिंग उद्देश्यों के लिए।


महान सलाह और एक बहुत अच्छी किताब!
मैरियन

रेड गेट कई अत्यंत सहायक मुक्त ई-पुस्तकें प्रदान करता है, और यह निश्चित रूप से बेहतर लोगों में से एक है। शानदार सुझाव।
मैट एम।

उनकी सभी किताबें ऐसा नहीं करती हैं, लेकिन कुज़नेत्सोव के "डिफेंसिव ..." पुस्तक के मुफ्त संस्करण में ट्रांजेक्शन अलगाव स्तर पर अंतिम 2 अध्याय और विकासशील संशोधन शामिल नहीं हैं जो संक्षिप्तता से बचे रहते हैं। मेरे लिए। वहां की सामग्री खरीद के लायक थी।
फिल हेल्मर

7

यह हमारा टेम्प्लेट है (त्रुटि लॉगिंग हटाया गया)

टिप्पणियाँ:

  • XACT_ABORT के बिना, सभी TXN शुरू और कमिट / रोलबैक जोड़े जाने चाहिए
  • एक प्रतिबद्ध कमी @@ TRANCOUNT
  • एक रोलबैक शून्य पर @@ TRANCOUNT देता है, इसलिए आपको 266 त्रुटि मिलेगी
  • आप वर्तमान लेयर को केवल लोड नहीं कर सकते (उदाहरण के लिए रोलबैक पर @@ TRANCOUNT)
  • XACT_ABORT 266 त्रुटि को दबा देता है
  • प्रत्येक संग्रहीत खरीद को उसी टेम्पलेट के अनुरूप होना चाहिए ताकि प्रत्येक कॉल परमाणु हो
  • रोलबैक चेक वास्तव में XACT_ABORT की वजह से बेमानी है। हालांकि, यह मुझे बेहतर महसूस कराता है, बिना इसके अजीब लगता है, और उन स्थितियों के लिए अनुमति देता है जहां आप इसे नहीं चाहते हैं
  • यह क्लाइंट साइड TXN (जैसे LINQ) के लिए अनुमति देता है
  • रेमस रुसानु में एक समान शेल होता है जो सेव पॉइंट का उपयोग करता है। मैं एक परमाणु DB कॉल पसंद करता हूं और उनके लेख की तरह आंशिक अपडेट का उपयोग नहीं करता हूं

... इसलिए ज़रूरत से ज़्यादा TXN न बनाएँ

तथापि,

CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
    SELECT @starttrancount = @@TRANCOUNT

    IF @starttrancount = 0
        BEGIN TRANSACTION

       [...Perform work, call nested procedures...]

    IF @starttrancount = 0 
        COMMIT TRANSACTION
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
        ROLLBACK TRANSACTION
    RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO

क्या होगा अगर @@ TRANCOUNT 0 से अधिक है? आप कोई काम नहीं करते हैं या कोई प्रतिक्रिया नहीं है?
kalalapy

@ पताल थैरेपी: एक नेस्टेड ट्रांजेक्शन जैसी कोई चीज नहीं है इसलिए हम एक और scribd.com/doc/49579859/33/Nested-Transactions-Are-Real
gbn

3

मैं ट्राई / कैच का उपयोग करता हूं, लेकिन मैं भी अधिक से अधिक जानकारी इकट्ठा करता हूं और यह लिखता हूं कि रोलबैक के बाद एक एररग्लॉग के लिए। इस उदाहरण में, "लॉगइनवेंट" एक संग्रहीत प्रक्रिया है जो एक EventLog तालिका में लिखती है, जिसमें क्या हुआ, उसका विवरण है। GetErrorInfo () एक फ़ंक्शन कॉल है जो सटीक त्रुटि संदेश देता है।

जब कोई त्रुटि होती है, तो जानकारी एकत्र की जाती है, प्रक्रिया त्रुटि से निपटने के अनुभाग के लिए नीचे आती है और एक रोलबैक जारी करती है। जानकारी लॉग को लिखी जाती है, फिर प्रक्रिया बाहर निकल जाती है।

शामिल अतिरिक्त प्रक्रिया / फ़ंक्शन कॉल को देखते हुए, यह शीर्ष पर थोड़ा सा लगता है। समस्या को डीबग करने का प्रयास करते समय यह विधि बहुत सहायक होती है।

LogEvent @Process, @Database, 'Blah blah blah डालने का प्रयास'
BEGIN TRY
  MyTable में डालें
  मान का चयन करें
    MyOtherTable से

  @rowcount = @@ ROWCOUNT चुनें
END TRY
-- गलती संभालना
BEGIN CATCH
  @error = ERROR_NUMBER () चुनें,
         @rowcount = -1,
         @TableAction = 'सम्मिलित करें',
         @TableName = @ डाटबेस + '
         @AdditionalInfo = '(ब्ला ब्ला ब्ला डालने का प्रयास)' + dbo.GetErrorInfo ()
   GOTO TableAccessError
END CATCH

।
।
।
।

TableAccessError:
IF (@@ TRANCOUNT> 0) रोलबैक
@output = Upper (@TableAction) + चुनें 
       'त्रुटि -' जबकि एक त्रुटि हुई 
       मामला (@TableAction)
         जब 'अपडेट' तो 'अपडेट'
         जब 'हटाओ' तब 'हटाना'
         बाकी @TableAction + 'ing'
       अंत + 
       'रिकॉर्ड' + 
       मामले (@TableAction) 
         जब 'से' चुनें तब ' 
         जब 'अपडेट' तब 'में' 
         जब 'डालें' तब 'में'
         और 'से'   
         अंत + 
         'द' + @TableName + 'तालिका।'
@output = @output + '@@ ERROR:' + कन्वर्ट (varchar (8), @ एरर) चुनें 
@output = @output + '@@ ROWCOUNT:' + कन्वर्ट (varchar (8), @ rowcount) का चयन करें 

@output = @output + isnull (@AdditionalInfo, '') का चयन करें
logEvent @Process, @Database, @Output को निष्पादित करें
RAISERROR (@ आउटपुट, 16,1) लॉग के साथ
@ReturnCode = -1 का चयन करें
GOTO THE_EXIT


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