2009-07-19 11 views
135

संग्रहीत प्रक्रिया में SET XACT_ABORT ON का उपयोग करने का क्या फायदा है?संग्रहीत प्रक्रिया में "सेट XACT_ABORT चालू" का उपयोग करने का क्या फायदा है?

+1

सुविधा के लिए एमएसडीएन रेफरी: https://msdn.microsoft.com/en-us/library/ms188792.aspx –

उत्तर

166

SET XACT_ABORT ON पूरे लेनदेन को रोलबैक करने के लिए SQL सर्वर को निर्देश देता है और रन-टाइम त्रुटि होने पर बैच को रोक देता है। यह आपको SQL सर्वर के बजाय क्लाइंट एप्लिकेशन पर होने वाले कमांड टाइमआउट जैसे मामलों में शामिल करता है (जो डिफ़ॉल्ट XACT_ABORT OFF सेटिंग द्वारा कवर नहीं किया गया है।)

चूंकि एक क्वेरी टाइमआउट लेनदेन को खोल देगा, SET XACT_ABORT ON अनुशंसित है स्पष्ट लेनदेन के साथ सभी संग्रहीत प्रक्रियाओं में (जब तक कि आपके पास अन्यथा करने का कोई विशिष्ट कारण न हो) क्योंकि खुले लेनदेन के साथ कनेक्शन पर काम करने वाले आवेदन के नतीजे विनाशकारी होते हैं।

वहाँ Dan Guzman's Blog पर एक वास्तव में महान अवलोकन दिया गया है,

+8

तो यह डिफ़ॉल्ट रूप से क्यों नहीं चल रहा है? –

1

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

25

मेरी राय सेट XACT_ABORT पर TRY शुरू/एसक्यूएल 2K5 में पकड़ने शुरू के अलावा द्वारा अप्रचलित बनाया गया था। ट्रांजैक्ट-एसक्यूएल में अपवाद ब्लॉक से पहले त्रुटियों को संभालना वास्तव में मुश्किल था और असंतुलित प्रक्रियाएं सभी बहुत आम थीं (प्रक्रियाओं की तुलना में बाहर निकलने पर प्रक्रियाओं का एक अलग @@ TRANCOUNT था)।

ट्रांजैक्ट-एसक्यूएल अपवाद हैंडलिंग के अतिरिक्त लेनदेन को सही ढंग से संतुलित करने की गारंटी देने वाली सही प्रक्रियाओं को लिखना बहुत आसान है। उदाहरण के लिए मैं का उपयोग इस template for exception handling and nested transactions:

create procedure [usp_my_procedure_name] 
as 
begin 
    set nocount on; 
    declare @trancount int; 
    set @trancount = @@trancount; 
    begin try 
     if @trancount = 0 
      begin transaction 
     else 
      save transaction usp_my_procedure_name; 

     -- Do the actual work here 

lbexit: 
     if @trancount = 0 
      commit; 
    end try 
    begin catch 
     declare @error int, @message varchar(4000), @xstate int; 
     select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE(); 
     if @xstate = -1 
      rollback; 
     if @xstate = 1 and @trancount = 0 
      rollback 
     if @xstate = 1 and @trancount > 0 
      rollback transaction usp_my_procedure_name; 

     raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ; 
    end catch 
end 
go 

यह मेरे परमाणु प्रक्रियाओं है कि वसूली योग्य त्रुटि के मामले में केवल अपने स्वयं के काम रोलबैक लिखने के लिए अनुमति देता है।

मुख्य मुद्दों Transact-SQL प्रक्रियाओं का सामना में से एक डेटा पवित्रता है: कभी कभी मापदंडों प्राप्त या टेबलों में डेटा डुप्लिकेट कुंजी त्रुटियों में जिसके परिणामस्वरूप सिर्फ सादा गलत कर रहे हैं, निर्देशात्मक, त्रुटियों विवश जाँच त्रुटियों विवश और इतने आगे और आगे। आखिरकार, यह वास्तव में इन बाधाओं की भूमिका है, यदि ये डेटा शुद्धता त्रुटियां असंभव होंगी और सभी व्यवसाय तर्क से पकड़े जाएंगे, तो बाधाएं अप्रचलित हो जाएंगी (प्रभाव के लिए नाटकीय अतिसंवेदनशीलता)। यदि XACT_ABORT चालू है तो इन सभी त्रुटियों के परिणामस्वरूप पूरे लेनदेन को खो दिया जा रहा है, क्योंकि अपवाद को व्यवस्थित करने वाले कोड अपवाद ब्लॉक को सक्षम करने के विरोध में। एक सामान्य उदाहरण एक आईएनएसईआरटी करने और पीके उल्लंघन पर अद्यतन को वापस करने की कोशिश कर रहा है।

+6

क्लाइंट टाइमआउट के अलावा ... और मेरा विचार एसईटी XACT_ABORT SQL 2005 में अधिक प्रभावी है क्योंकि व्यवहार अधिक अनुमानित है: बहुत कम बैच त्रुटियों को निरस्त कर रहा है। – gbn

+2

ग्राहक * टाइमआउट * एप्लिकेशन कीड़े हैं। कोई ऐप कभी भी कमांड टाइमआउट लागू नहीं करना चाहिए। क्या यह एक बेहद खराब अभ्यास है कि डिफ़ॉल्ट SqlClient टाइमआउट मुझे हर बार सिरदर्द देता है जब मुझे लगता है कि वे ऐसा कुछ कैसे भेज सकते हैं। आप टाइमआउट समस्या के आसपास अपने पूरे ट्रांजैक्ट-एसक्यूएल त्रुटि को संभालने में मार्गदर्शन कर सकते हैं, या आप क्लाइंट को सही तरीके से कोड कर सकते हैं और त्रुटि प्रबंधन में व्यावसायिक समस्याओं का समाधान कर सकते हैं। बेशक, मेरा विचार डेवलपर बिंदु से है। व्यवस्थापक/डीबीए भूमिका में आमतौर पर दुनिया को अलग-अलग देखते हैं, क्योंकि वे अन्य बनाने वाले ऐप्स के साथ फंस जाते हैं। –

+6

मैं कुछ हद तक सहमत हूं, लेकिन मैं अपनी घटनाओं को सभी घटनाओं के आसपास संभालने की योजना बना रहा हूं, क्योंकि मुझे पता है कि कमांड टाइमआउट होने पर मुझे डेवलपर डीबीए के रूप में दोष मिलेगा। – gbn

19

MSDN का हवाला देते हुए:

जब सेट XACT_ABORT चालू होता है, अगर एक Transact SQL कथन एक रन-टाइम त्रुटि को जन्म देती है, पूरे लेन-देन समाप्त और वापस लुढ़का है। जब SET XACT_ABORT बंद हो जाता है, तो कुछ मामलों में केवल ट्रांजैक्ट-एसक्यूएल कथन जो त्रुटि उठाता है उसे वापस ले जाया जाता है और लेनदेन प्रसंस्करण जारी रहता है।

अभ्यास में इसका मतलब है कि कुछ कथन विफल हो सकते हैं, लेनदेन को 'आंशिक रूप से पूरा' छोड़कर, और कॉलर के लिए इस विफलता का कोई संकेत नहीं हो सकता है।

एक साधारण उदाहरण:

INSERT INTO t1 VALUES (1/0)  
INSERT INTO t2 VALUES (1/1)  
SELECT 'Everything is fine' 

इस कोड 'सफलतापूर्वक' XACT_ABORT बंद के साथ अमल होता है, और (XACT_ABORT पर के साथ एक त्रुटि 't2 में डालने' के साथ समाप्त होगा निष्पादित नहीं किया जाएगा, और एक क्लाइंट अनुप्रयोग एक अपवाद उठाएगा)।

अधिक लचीला दृष्टिकोण के रूप में, आप प्रत्येक कथन (पुराने स्कूल) के बाद @@ ERROR की जांच कर सकते हैं, या TRY का उपयोग कर सकते हैं ... कैच ब्लॉक (MSSQL2005 +)। व्यक्तिगत रूप से जब भी कुछ उन्नत त्रुटि प्रबंधन के लिए कोई कारण नहीं है, तो मैं XACT_ABORT चालू करना पसंद करता हूं।

3

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

संबंधित मुद्दे

 संबंधित मुद्दे