EXECUTE के बाद ट्रांजेक्शन काउंट BEGIN और COMMIT स्टेटमेंट की बेमेल संख्या को दर्शाता है। पिछली संख्या = 1, वर्तमान गणना = 0


94

मेरे पास एक Insertसंग्रहीत प्रक्रिया है जो डेटा को फीड करेगी Table1और Column1मूल्य प्राप्त करेगी और Table1दूसरी संग्रहीत प्रक्रिया को कॉल करेगी जो टेबल 2 को खिलाएगी।

लेकिन जब मैं दूसरी संग्रहीत प्रक्रिया कहता हूं:

Exec USPStoredProcName

मुझे निम्नलिखित त्रुटि मिलती है:

EXECUTE के बाद ट्रांजेक्शन काउंट BEGIN और COMMIT स्टेटमेंट की बेमेल संख्या को दर्शाता है। पिछली संख्या = 1, वर्तमान गणना = 0।

मैंने इस तरह के अन्य सवालों के जवाब पढ़े हैं और यह पता लगाने में असमर्थ हूं कि वास्तव में प्रतिबद्ध गणना कहां गड़बड़ हो रही है।


क्या आपके पास अपनी प्रक्रिया में कोई TRY / CATCH ब्लॉक है?
रेमस रुसानु

हां मेरे पास TRY / CATCH ब्लॉक है
विग्नेश कुमार A

जवाबों:


109

यदि आपके पास TRY / CATCH ब्लॉक है, तो संभावित कारण यह है कि आप एक ट्रांज़ैक्शन एबॉर्ट अपवाद को पकड़ रहे हैं और जारी रखें। CATCH ब्लॉक में आपको हमेशा XACT_STATE()उपयुक्त गर्भपात और अक्षम (डूमेड) लेनदेन की जांच करनी चाहिए । यदि आपका कॉलर लेन-देन शुरू करता है और कैली हिट करता है, तो कहें, एक गतिरोध (जिसने लेन-देन निरस्त कर दिया है), कॉलली को संचार करने के लिए कैली कैसे जा रहा है कि लेन-देन निरस्त कर दिया गया था और इसे 'व्यापार की तरह सामान्य रूप से' जारी नहीं रखना चाहिए? एकमात्र संभव तरीका एक अपवाद को फिर से उठाना है, जिससे कॉलर को स्थिति को संभालने के लिए मजबूर किया जा सके। यदि आप चुपचाप एक निरस्त लेन-देन को निगल लेते हैं और फोन करने वाला यह मानता है कि मूल लेनदेन में अभी भी है, केवल तबाही सुनिश्चित कर सकता है (और आपको जो त्रुटि मिलती है वह उसी तरह है जैसे इंजन खुद को बचाने की कोशिश करता है)।

मेरा सुझाव है कि आप अपवाद हैंडलिंग और नेस्टेड लेनदेन पर जाएं जो एक पैटर्न दिखाता है जिसका उपयोग नेस्टेड लेनदेन और अपवादों के साथ किया जा सकता है:

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

3
आपकी सहायता के लिए धन्यवाद। Raiserror का उपयोग करके मुझे समस्या मिल गई है। यह पूरी तरह से NULL फ़ील्ड में NULL मान सम्मिलित करने की कोशिश कर रहा है
Vignesh Kumar A

लेकिन एक बाधा जाँच सत्यापन लेनदेन को रद्द नहीं करेगा। क्या आप स्पष्ट रूप से पकड़ में वापस आ रहे हैं, या आप उपयोग करते हैं xact_abort on?
रेमस रुसानु

Im स्पष्ट रूप से वापस रोलिंग
विग्नेश कुमार A

2
मैंने इस पैटर्न की कोशिश की है, लेकिन फिर भी यह काम नहीं करता है - जब मेरे पास एक बाहरी लेनदेन होता है तो यह पैटर्न एक सेवपॉइंट बनाता है और एक महत्वपूर्ण त्रुटि (असंगत लेनदेन) के मामले में बाहरी लेनदेन को रोलबैक करता है - यह अभी भी प्रवेश करने से पहले एक @@ trancount = 1 का कारण बनता है। प्रक्रिया और @@ trancount = 0 जब यह बाहर निकलता है
गौरैया

3
मुझे लगता है कि पकड़ में इस बिट गलत है: if @xstate = -1 rollback; इस को देखते हुए MSDN उदाहरण के लिए, हम चाहिए नहीं पूरा लेन-देन जब तक कि वहाँ था रोलबैक नहीं एक बाहरी लेन-देन (है कि, जब तक हमने किया begin tran)। मुझे लगता है कि प्रक्रिया केवल तभी होनी चाहिए rollbackजब हमने लेनदेन शुरू किया था, जो @ गौरैया की समस्या को ठीक करेगा।
निक

59

मुझे यह समस्या भी हुई। मेरे लिए, कारण यह था कि मैं कर रहा था

return
commit

के बजाय

commit
return   

एक संग्रहीत प्रक्रिया में।


4
@seguso - यह बहुत मददगार था। साझा करने के लिए धन्यवाद। कभी कभी कुछ तो बस धूल के नीचे हो जाता है। उन्हें सबसे अच्छा लगता है।
लियो गुरदियन

यह मेरे लिए समस्या थी, लेकिन कम स्पष्ट थी क्योंकि हम अपने डेटा एक्सेस लेयर के माध्यम से एक बड़े लेन-देन में कई स्पोक कॉल लपेट रहे थे - इसलिए केवल स्प्रो को देखकर आप यह नहीं बता सकते थे कि वहाँ एक लेनदेन था। यदि आपके पास यह समस्या है, तो सुनिश्चित करें कि वहाँ एक ही नहीं है जो कि स्पार्क के बाहर कुछ है जो एक लेनदेन बना रहा है। अगर वहाँ है, तो आप स्पोक के भीतर रिटर्न स्टेटमेंट का उपयोग करने में सक्षम नहीं हो सकते हैं।
EF0

यह मैं था, मेरा एक लेन-देन था और एक / दूसरे बयान में मेरे प्रतिबद्ध लेनदेन से पहले लौट रहा था
केविन

18

यह आम तौर पर तब होता है जब लेनदेन शुरू किया जाता है और या तो यह प्रतिबद्ध नहीं होता है या यह रोलबैक नहीं होता है।

यदि आपके संग्रहीत कार्यविधि में त्रुटि आती है, तो यह डेटाबेस तालिकाओं को लॉक कर सकता है क्योंकि अपवाद हैंडलिंग की अनुपस्थिति में कुछ रनटाइम त्रुटियों के कारण लेनदेन पूरा नहीं हुआ है। आप नीचे दिए गए अपवाद हैंडलिंग का उपयोग कर सकते हैं। XACT_ABORT को सेट करें

SET XACT_ABORT ON
SET NoCount ON
Begin Try 
     BEGIN TRANSACTION 
        //Insert ,update queries    
     COMMIT
End Try 
Begin Catch 
     ROLLBACK
End Catch

स्रोत


अगर ऐसा होता तो उद्धृत प्रश्न / उत्तर का अर्थ शायद यह होना चाहिए कि इसे डुप्लिकेट और बंद के रूप में चिह्नित किया जाना चाहिए
मार्क शुल्त्स

10

इस बात से अवगत रहें कि यदि आप नेस्टेड लेन-देन का उपयोग करते हैं, तो एक रोलबैक ऑपरेशन बाहरी-सबसे एक सहित सभी नेस्टेड लेनदेन को वापस रोल करता है।

यह TRY / CATCH के संयोजन में उपयोग के साथ, आपके द्वारा बताई गई त्रुटि के परिणामस्वरूप हो सकता है। अधिक देखें यहाँ


5

यह तब भी हो सकता है यदि आपकी संग्रहीत प्रक्रिया लेनदेन खोलने के बाद संकलित विफलता का सामना करती है (जैसे तालिका नहीं मिली, अमान्य स्तंभ नाम)।

मैंने पाया कि मुझे 2 संग्रहीत प्रक्रियाओं को एक "कार्यकर्ता" एक और एक रैपर का उपयोग करना था, जिसमें रेमस रुसानु द्वारा उल्लिखित तर्क के समान दोनों को पकड़ने / पकड़ने की कोशिश की गई थी। वर्कर कैच का उपयोग "सामान्य" विफलताओं को संभालने के लिए किया जाता है और कम्पाइलर विफलता त्रुटियों को संभालने के लिए रैपर को पकड़ा जाता है।

https://msdn.microsoft.com/en-us/library/ms175976.aspx

त्रुटियां एक TRY से प्रभावित ... CATCH निर्माण

निम्नलिखित प्रकार की त्रुटियों को एक CATCH ब्लॉक द्वारा नियंत्रित नहीं किया जाता है जब वे TRY के रूप में निष्पादन के समान स्तर पर होते हैं ... CATCH परिणाम इस प्रकार हैं:

  • संकलित त्रुटियां, जैसे वाक्यविन्यास त्रुटियां , जो बैच को चलने से रोकती हैं।
  • कथन-स्तर पुनर्संयोजन के दौरान होने वाली त्रुटियां, जैसे ऑब्जेक्ट नाम रिज़ॉल्यूशन त्रुटियां, जो आस्थगित नाम रिज़ॉल्यूशन के कारण संकलन के बाद होती हैं।

उम्मीद है कि यह किसी और को डीबगिंग के कुछ घंटे बचाने में मदद करता है ...


1
धन्यवाद जस्टिन। अच्छा अवलोकन। मेरे मामले में मैं एक अद्यतन के अंदर एक समुच्चय कर रहा था जो एसपी सेव के दौरान संकलन त्रुटियों का उत्पादन नहीं करता है, लेकिन वास्तव में अमान्य सिंटैक्स था - "एक सारांश एक अद्यतन कथन की सेट सूची में प्रकट नहीं हो सकता"
kuklei

4

मेरे मामले में, त्रुटि RETURNअंदर से हुई थी BEGIN TRANSACTION। तो मेरे पास कुछ ऐसा था:

Begin Transaction
 If (@something = 'foo')
 Begin
     --- do some stuff
     Return
 End
commit

और यह होना चाहिए:

Begin Transaction
 If (@something = 'foo')
 Begin
     --- do some stuff
     Rollback Transaction ----- THIS WAS MISSING
     Return
 End
commit

2

मेरे लिए व्यापक डिबगिंग के बाद फिक्स एक साधारण लापता थ्रो था; रोलबैक के बाद पकड़ में बयान। इसके बिना यह बदसूरत त्रुटि संदेश है जिसे आप समाप्त करते हैं।

begin catch
    if @@trancount > 0 rollback transaction;
    throw; --allows capture of useful info when an exception happens within the transaction
end catch

2

मेरे पास एक ही त्रुटि संदेश था, मेरी गलती यह थी कि मुझे COMMIT TRANSACTION लाइन के अंत में एक अर्धविराम मिला था


इस के रूप में सरल। इसके अलावा, मेरे मामले में एक 'रोलबैक' कथन की आवश्यकता थी, जिसमें एसपी को पूरी तरह से निष्पादित नहीं किया जाएगा। बस लेनदेन को बंद करने / समाप्त करने के लिए।
J Cordero

1

मुझे अपने लेन-देन से इस कथन को छोड़ने के बाद एक बार इस त्रुटि का सामना करना पड़ा।

COMMIT TRANSACTION [MyTransactionName]

1

मेरी राय में स्वीकृत जवाब ज्यादातर मामलों में एक ओवरकिल है।

त्रुटि का कारण अक्सर बेगिन और COMMIT का बेमेल है जैसा कि त्रुटि द्वारा स्पष्ट रूप से कहा गया है। इसका उपयोग करने का अर्थ है:

Begin
  Begin
    -- your query here
  End
commit

के बजाय

Begin Transaction
  Begin
    -- your query here
  End
commit

इस त्रुटि का कारण बनता है!


1

सुनिश्चित करें कि आपके पास एक ही प्रक्रिया / क्वेरी में एक से अधिक लेनदेन नहीं हैं, जिसमें से एक या एक से अधिक को छोड़ दिया गया है।

मेरे मामले में, मैंने गलती से क्वेरी में BEGIN TRAN बयान दिया था


1

यह उस तरीके पर भी निर्भर कर सकता है जिस तरह से आप अपने सी # कोड से एसपी को आमंत्रित कर रहे हैं। यदि SP कुछ तालिका प्रकार मान लौटाता है, तो SP को ExecuteStoreQuery के साथ आमंत्रित करें, और यदि SP कोई मान नहीं लौटाता है तो ExecuteStoreCommand के साथ SP को आमंत्रित करें


1

प्रयोग करने से बचें

RETURN

बयान जब आप उपयोग कर रहे हैं

BEGIN TRY
    ... 
END TRY

BEGIN CATCH
    ...
END CATCH

तथा

BEGIN, COMMIT & ROLLBACK

एसक्यूएल संग्रहीत प्रक्रियाओं में बयान


0

यदि आप किसी चीज़ की कोड संरचना कर रहे हैं जैसे:

SELECT 151
RETURN -151

फिर उपयोग करें:

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