डिफ़ॉल्ट रूप से, लेन-देन, अधिकांश समय होता है, जब कोई त्रुटि होती है, तो स्वचालित रूप से रोल-बैक / रद्द नहीं किया जाता है। यह आमतौर पर एक समस्या नहीं है जब तक आपके पास उचित त्रुटि से निपटने और ROLLBACK
अपने आप को कॉल करने के लिए नहीं है । हालांकि, कभी-कभी चीजें जटिल हो जाती हैं, जैसे कि बैच-एबॉर्टिंग त्रुटियों के मामले में, या जब OPENQUERY
(या सामान्य रूप से लिंक्ड सर्वर) का उपयोग करते हुए और रिमोट सिस्टम पर कोई त्रुटि होती है। हालांकि अधिकांश त्रुटियों का उपयोग करके फंसे हुए हो सकते हैं TRY...CATCH
, दो ऐसे हैं जो उस तरह से नहीं फंस सकते हैं (यह याद नहीं है कि इस समय कौन से हैं, हालांकि - शोध)। इन मामलों में, आपको SET XACT_ABORT ON
लेन-देन को ठीक से रोलबैक करने के लिए उपयोग करना चाहिए ।
SET XACT_ABORT के कारण SQL सर्वर तुरंत किसी भी Transaction (यदि कोई सक्रिय है) को वापस कर देता है और कोई भी त्रुटि होने पर बैच को निरस्त कर देता है। SQL सर्वर 2005 से पहले यह सेटिंग मौजूद थी, जिसने TRY...CATCH
निर्माण शुरू किया था। अधिकांश भाग के लिए, TRY...CATCH
अधिकांश स्थितियों को संभालता है और इसलिए ज्यादातर इसकी आवश्यकता को पूरा करता है XACT_ABORT ON
। हालांकि, जब उपयोग OPENQUERY
(और संभवतः एक अन्य परिदृश्य जिसे मैं इस समय याद नहीं कर सकता हूं), तो आपको अभी भी उपयोग करने की आवश्यकता होगी SET XACT_ABORT ON;
।
आपके पास हमेशा उचित त्रुटि हैंडलिंग होनी चाहिए, विशेष रूप से लेन-देन का उपयोग करते समय। TRY...CATCH
निर्माण, SQL सर्वर 2005 में शुरू की, लगभग सभी स्थितियों, के लिए परीक्षण पर एक स्वागत सुधार से निपटने में एक साधन प्रदान करता @@ERROR
प्रत्येक बयान है, जो बैच-निरस्त त्रुटियों के साथ ज्यादा मदद नहीं की है।
TRY...CATCH
हालांकि, एक नया "राज्य" शुरू किया। जब नहीं का उपयोग कर TRY...CATCH
निर्माण, अगर आप एक सक्रिय लेन-देन है और एक त्रुटि तब होती है, तो कई रास्ते है कि लिया जा सकता है:
XACT_ABORT OFF
और कथन-निरस्त करने की त्रुटि: लेन-देन अभी भी सक्रिय है और यदि कोई हो, तो अगले कथन के साथ प्रसंस्करण जारी है ।
XACT_ABORT OFF
और सबसे बैच-गर्भपात की त्रुटियां: लेन-देन अभी भी सक्रिय है और अगले बैच के साथ प्रसंस्करण जारी है , यदि कोई हो।
XACT_ABORT OFF
और कुछ बैच-गर्भपात की त्रुटियां: लेन-देन लुढ़का हुआ है और अगले बैच के साथ प्रसंस्करण जारी है , यदि कोई हो।
XACT_ABORT ON
और कोई त्रुटि: लेन-देन लुढ़का हुआ है और अगले बैच के साथ प्रसंस्करण जारी है , यदि कोई हो।
जब भी, TRY...CATCH
बैच-गर्भपात की त्रुटियों का उपयोग करते हुए , बैच को निरस्त न करें, बल्कि CATCH
ब्लॉक पर नियंत्रण स्थानांतरित करें । कब XACT_ABORT
है OFF
, लेन-देन अभी भी अधिकांश समय तक सक्रिय रहेगा, और आपको COMMIT
सबसे अधिक संभावना होगी , या ROLLBACK
। लेकिन जब कुछ बैच-एबॉर्टिंग एरर (जैसे कि OPENQUERY
), या जब XACT_ABORT
हो ON
, का सामना करना पड़ता है , तो ट्रांजेक्शन एक नई स्थिति में होगा, "अनबिकेबल"। इस अवस्था में आप COMMIT
न तो कोई DML ऑपरेशन कर सकते हैं और न ही कर सकते हैं। आप सभी कर सकते हैं ROLLBACK
और SELECT
बयान। हालाँकि, इस "असुविधाजनक" स्थिति में, लेन-देन त्रुटि होने पर वापस ले लिया गया था, और इसे जारी करना ROLLBACK
केवल एक औपचारिकता है, लेकिन एक ऐसा किया जाना चाहिए।
एक फ़ंक्शन, XACT_STATE , का उपयोग यह निर्धारित करने के लिए किया जा सकता है कि क्या लेन-देन सक्रिय , असुविधाजनक है या मौजूद नहीं है। यह CATCH
निर्धारित करने के लिए कि -1
परीक्षण के बजाय परिणाम (यानी असुविधाजनक) है, तो यह निर्धारित करने के लिए ब्लॉक में इस फ़ंक्शन की जांच करने के लिए (कुछ, कम से कम) की सिफारिश की जाती है @@TRANCOUNT > 0
। लेकिन इसके साथ XACT_ABORT ON
, यह एकमात्र संभव राज्य होना चाहिए, इसलिए ऐसा लगता है कि इसके लिए परीक्षण @@TRANCOUNT > 0
और XACT_STATE() <> 0
समकक्ष हैं। दूसरी ओर, जब XACT_ABORT
होता है OFF
और एक सक्रिय लेनदेन होता है, तो 1
या तो या ब्लॉक -1
में एक राज्य होना संभव है CATCH
, जो COMMIT
इसके बजाय जारी करने की संभावना के लिए अनुमति देता है ROLLBACK
(हालांकि, मैं किसी के लिए एक मामले के बारे में नहीं सोच सकता करना चाहेगाCOMMIT
यदि लेनदेन सराहनीय है)। अधिक जानकारी और प्रयोग पर अनुसंधान XACT_STATE()
एक के भीतर CATCH
के साथ ब्लॉक XACT_ABORT ON
: निम्नलिखित DBA.SE सवाल का मेरा उत्तर में पाया जा सकता में क्या मामलों एक सौदे कैच ब्लॉक के अंदर से प्रतिबद्ध किया जा सकता है जब XACT_ABORT चालू पर सेट है? । कृपया ध्यान दें कि इसके साथ एक मामूली बग है XACT_STATE()
जो इसे 1
कुछ परिदृश्यों में गलत तरीके से वापस करने का कारण बनता है: XACT_STATE () रिटर्न 1 जब कुछ सिस्टम चर के साथ चयन में उपयोग किया जाता है, लेकिन बिना खंड से
spNewBilling3
एक त्रुटि फेंकता है, लेकिन आप रोल वापस नहीं करना चाहताspNewBilling2
याspNewBilling1
, तो बस हटाने[begin|rollback|commit] transaction createSavebillinginvoice
सेspSavesomename
।