SET XACT_ABORT ONसंग्रहीत प्रक्रिया में उपयोग करने का क्या लाभ है ?
SET XACT_ABORT ONसंग्रहीत प्रक्रिया में उपयोग करने का क्या लाभ है ?
जवाबों:
SET XACT_ABORT ONSQL सर्वर को संपूर्ण लेनदेन को रोलबैक करने और रन-टाइम त्रुटि होने पर बैच को निरस्त करने का निर्देश देता है। यह आपको SQL Server के भीतर (जो डिफ़ॉल्ट XACT_ABORT OFFसेटिंग द्वारा कवर नहीं किया गया है ) के बजाय क्लाइंट एप्लिकेशन पर होने वाले कमांड टाइमआउट जैसे मामलों में शामिल करता है ।
चूंकि क्वेरी टाइमआउट लेन-देन को खुला छोड़ देगा, SET XACT_ABORT ONस्पष्ट लेनदेन के साथ सभी संग्रहीत प्रक्रियाओं में अनुशंसित है (जब तक कि आपके पास अन्यथा करने का कोई विशिष्ट कारण न हो) क्योंकि एक खुले लेनदेन के साथ कनेक्शन पर काम करने वाले आवेदन के परिणाम विनाशकारी होते हैं।
डैन गुज़मैन के ब्लॉग पर वास्तव में बहुत अच्छा अवलोकन है ,
BEGIN TRY- BEGIN CATCHऔर Sql में ब्लॉक के ROLLBACKसाथ XACT_ABORT अभी भी आवश्यक है BEGIN CATCH?
BEGIN TRY- BEGIN CATCHक्लाइंट एप्लिकेशन पर होने वाली टाइमआउट जैसी चीजों को नहीं पकड़ पाएगा, और कुछ SQL त्रुटियां भी उपलब्ध नहीं हैं, जो आपको एक खुले लेनदेन के साथ छोड़ देती हैं, जहां आप एक की उम्मीद नहीं करेंगे।
मेरी राय में SET XACT_ABORT ON को SQL 2k5 में BEGIN TRY / BEGIN CATCH के अलावा अप्रचलित कर दिया गया था। Transact-SQL में अपवाद ब्लॉकों से पहले त्रुटियों को संभालना वास्तव में मुश्किल था और असंतुलित प्रक्रियाएं सभी बहुत सामान्य थीं (प्रक्रियाएं जो प्रविष्टि की तुलना में एक अलग @@ TRANCOUNT थी)।
Transact-SQL अपवाद को जोड़ने के साथ लेनदेन को ठीक से संतुलित करने की गारंटी देने वाली सही प्रक्रियाओं को लिखना बहुत आसान है। उदाहरण के लिए मैं अपवाद हैंडलिंग और नेस्टेड लेनदेन के लिए इस टेम्पलेट का उपयोग करता हूं :
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 चालू है, तो इन सभी त्रुटियों के परिणामस्वरूप संपूर्ण लेन-देन खो जाता है, अपवाद को ब्लॉक करने में सक्षम होने का विरोध करने के रूप में, जो अपवाद के रूप में इनायत से संभालते हैं। एक विशिष्ट उदाहरण एक INSERT करने की कोशिश कर रहा है और PK उल्लंघन पर अद्यतन करने के लिए पुन: प्रस्तुत कर रहा है।
MSDN का हवाला देते हुए :
जब SET XACT_ABORT चालू होता है, यदि कोई Transact-SQL कथन रन-टाइम त्रुटि उठाता है, तो संपूर्ण लेन-देन समाप्त हो जाता है और वापस चला जाता है। जब SET XACT_ABORT बंद होता है, तो कुछ मामलों में केवल Transact-SQL स्टेटमेंट जो त्रुटि उठाता है, उसे वापस ले लिया जाता है और ट्रांजेक्शन प्रोसेस हो जाता है।
व्यवहार में इसका मतलब यह है कि कुछ बयान विफल हो सकते हैं, लेन-देन को 'आंशिक रूप से पूरा' छोड़कर, और कॉल करने वाले के लिए इस विफलता का कोई संकेत नहीं हो सकता है।
एक सरल उदाहरण:
INSERT INTO t1 VALUES (1/0)
INSERT INTO t2 VALUES (1/1)
SELECT 'Everything is fine'
यह कोड XACT_ABORT OFF के साथ 'सफलतापूर्वक' निष्पादित करेगा, और XACT_ABORT ON ('INSERT INTO t2' के साथ एक त्रुटि के साथ समाप्त हो जाएगा, निष्पादित नहीं किया जाएगा और एक ग्राहक एप्लिकेशन एक अपवाद बढ़ाएगा)।
अधिक लचीले दृष्टिकोण के रूप में, आप प्रत्येक कथन (पुराने स्कूल) के बाद @@ ERROR की जांच कर सकते हैं, या TRY ... CATCH ब्लॉक (MSSQL2005 +) का उपयोग कर सकते हैं। जब भी कुछ उन्नत त्रुटि से निपटने का कोई कारण नहीं है, व्यक्तिगत रूप से मैं XACT_ABORT को सेट करना पसंद करता हूं।
क्लाइंट टाइमआउट और उन्हें संभालने के लिए XACT_ABORT के उपयोग के बारे में, मेरी राय में ग्राहक API में SqlClient जैसे टाइमआउट होने का कम से कम एक बहुत अच्छा कारण है, और वह है SQL सर्वर कोड में होने वाले गतिरोध से क्लाइंट एप्लिकेशन कोड की रक्षा करना। इस मामले में क्लाइंट कोड की कोई गलती नहीं है, लेकिन इसे सर्वर पर पूरा होने के लिए कमांड के इंतजार में हमेशा के लिए अवरुद्ध होने से बचाने के लिए है। इसके विपरीत, यदि क्लाइंट कोड को क्लाइंट कोड की सुरक्षा के लिए मौजूद होना है, तो क्या XACT_ABORT ON को क्लाइंट कोड से सर्वर कोड की सुरक्षा करनी है, अगर क्लाइंट कोड से अधिक समय लगता है तो ग्राहक को इंतजार करने की इच्छा होती है।