डायनेमिक SQL बैकअप कमांड के लिए try / catch का उपयोग करते समय त्रुटि विवरण कैसे लॉग करें


10

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

एसपी के भीतर की कोशिश करो / पकड़ो:

    begin try
        execute sp_executesql @sql;  -- a backup command
    end try
    begin catch  
        print ERROR_MESSAGE();  -- save to log, etc.
    end catch

का परिणाम

50000: usp_Backup: 117: BACKUP DATABASE असामान्य रूप से समाप्त हो रहा है।

कच्‍चा आदेश जारी करने का भय:

    backup DATABASE someDb to disk...

बेहतर विवरण में परिणाम:

लुकअप त्रुटि - SQL सर्वर डेटाबेस त्रुटि: फ़ाइल पर एक गैर-अपरिवर्तनीय I / O त्रुटि आई "H: \ FolderName \ Filename.bak:" 112 (डिस्क पर पर्याप्त स्थान नहीं है।)।

क्या संग्रहित प्रक्रिया के भीतर चर में इन विवरणों को पकड़ने का एक तरीका है (लॉग इन करें, कॉल बैक करने के लिए, रिट्री लॉजिक के लिए)? ऐसा लगता है कि विवरण संदेश चैनल पर आ रहे हैं, लेकिन मैं उन्हें एसपी के भीतर उपलब्ध कराना चाहूंगा।


आप इसे देखना चाहते हैं: stackoverflow.com/questions/5966670/…
8kb

जवाबों:


13

जब BACKUP DATABASEकोई त्रुटि उत्पन्न करता है, तो यह वास्तव में दो उत्पन्न करता है। दुर्भाग्य से TRY/CATCHपहली त्रुटि को पकड़ने में सक्षम नहीं है; यह केवल दूसरी त्रुटि पकड़ता है।

मैं आपका सर्वश्रेष्ठ दांव असली कारण पर कब्जा करने के पीछे एक असफल बैकअप के माध्यम से अपने बैकअप को स्वचालित करने के लिए है पर शक SQLCMD (साथ -oएक फाइल करने के लिए उत्पादन भेजने के लिए), लघु उद्योगों, सी #, PowerShell आदि सभी जिनमें से आप बहुत अधिक नियंत्रण पर कब्जा करने से अधिक दे देंगे सभी त्रुटियों की।

टिप्पणी में SO उत्तर का उपयोग करने का सुझाव देता है DBCC OUTPUTBUFFER- जबकि यह संभव है, यह बिल्कुल भी बच्चे के खेल की तरह नहीं लगता है। Erland Sommarskog की साइट से इस प्रक्रिया के साथ मज़े करने के लिए स्वतंत्र महसूस करें , लेकिन यह अभी भी संयोजन के साथ अच्छी तरह से काम नहीं करता है TRY/CATCH

एकमात्र तरीका मुझे लगता है कि त्रुटि संदेश को कैप्चर करने में सक्षम होना चाहिए spGET_LastErrorMessage, अगर वास्तविक त्रुटि फेंक दी जाती है। यदि आप इसे एक TRY/CATCHत्रुटि में लपेटते हैं तो निगल लिया जाता है और संग्रहीत कार्यविधि कुछ नहीं करती है:

BEGIN TRY
  EXEC sp_executesql N'backup that fails...';
END TRY
BEGIN CATCH
  EXEC dbo.spGet_LastErrorMessage;
END CATCH

SQL सर्वर <2012 में आप स्वयं त्रुटि दोबारा नहीं उठा सकते, लेकिन आप SQL सर्वर 2012 और नए में कर सकते हैं। तो ये दो भिन्नताएँ काम करती हैं:

CREATE PROCEDURE dbo.dothebackup
AS
BEGIN
  SET NOCOUNT ON;
  EXEC sp_executesql N'backup that fails...';
END
GO

EXEC dbo.dothebackup;
EXEC dbo.spGET_LastErrorMessage;

या 2012 और इसके बाद के संस्करण में, यह काम करता है, लेकिन एक बड़ी डिग्री के उद्देश्य को हरा देता है TRY/CATCH, क्योंकि मूल त्रुटि अभी भी फेंक दी जाती है:

CREATE PROCEDURE dbo.dothebackup2
AS
BEGIN
  SET NOCOUNT ON;
  BEGIN TRY
    EXEC sp_executesql N'backup that fails...';
  END TRY
  BEGIN CATCH
    THROW;
  END CATCH
END
GO

EXEC dbo.dothebackup2;
EXEC dbo.spGET_LastErrorMessage;

इन दोनों मामलों में, त्रुटि अभी भी ग्राहक को फेंक दी गई है, निश्चित रूप से। इसलिए यदि आप TRY/CATCHउससे बचने के लिए उपयोग कर रहे हैं , जब तक कि कुछ खामी नहीं है, जिसके बारे में मैं नहीं सोच रहा हूं, मुझे डर है कि आपको चुनाव करना होगा ... या तो उपयोगकर्ता को त्रुटि दें और उसके बारे में विवरण कैप्चर करने में सक्षम हों यह, या त्रुटि और वास्तविक कारण दोनों को दबा देता है।


जैसा कि यह हास्यास्पद है, सोमारस्कॉग दृष्टिकोण इस सवाल से बाहर नहीं निकलता है अगर मैं सिर्फ एक इंटरफ़ेस के भीतर कॉलर को कुछ संदर्भ प्रदान करना चाहता था। एक अलग प्रक्रिया शुरू करने से बेहतर है। क्या आप कह रहे हैं कि यह TRY / CATCH के भीतर काम नहीं करेगा?
क्रुकसेक

@ क्रोक्यूसेक मैंने एक बदलाव की कोशिश की और परिणाम खाली आया। मैं इसे आज एक और शॉट दूँगा।
हारून बर्ट्रेंड

कोई त्रुटि नहीं होने की स्थिति में, LastErrorMessage () सत्र से किसी पिछली त्रुटि के परिणाम प्राप्त करता है? फिर यदि अंतिम दो निष्पादन स्क्रिप्ट के रूप में चलाए जाते हैं, तो शायद पहले निष्पादन को एक कोशिश / पकड़ के भीतर लपेटा जा सकता है और पकड़ के भीतर, एक चर सेट करें, फिर फेंक दें। फिर LastError तभी कहलाती है जब वेरिएबल सेट होता है। मान लें कि री-थ्रो 2 कॉल को नहीं छोड़ता है जो मुझे लगता है कि आमतौर पर एक स्क्रिप्टिंग संदर्भ में सच है। मैं अभी भी अंत में इस दृष्टिकोण का उपयोग करने में सक्षम नहीं हो सकता, क्योंकि अगर मुझे सही तरीके से समझा जाए तो यह सब एक एसपी के भीतर नहीं रखा जा सकता है। हालांकि धन्यवाद!
क्रौसेक

2

वैसे मुझे पता है कि यह एक पुराना धागा है, और मुझे पता है कि मैं जो प्रस्ताव देने वाला हूं, वह एक जटिल हैक है, लेकिन अगर यह किसी की मदद कर सकता है, तो यहां जाता है: चूंकि ये बैकअप त्रुटियां लॉग इन हो जाती हैं, आप xp_readerrorlog का उपयोग कर सकते हैं संबंधित संदेश (त्रुटि या जानकारी) के लिए लॉग को परिमार्जन करने के लिए ब्लॉक करें। आप xp_readerrorlog params के लिए चारों ओर Google कर सकते हैं, लेकिन संक्षेप में आप खोज-स्ट्रिंग और एक शुरुआती समय फ़िल्टर की कल्पना कर सकते हैं जो इस मामले में उपयोगी हैं। यकीन नहीं होता कि यह आपके रिट्री लॉजिक में मदद करेगा, लेकिन लॉगिंग के लिए जानकारी या त्रुटियों को पकड़ने के लिए, मैं कुछ इस तरह से आया ...

IF OBJECT_ID('tempdb.dbo.#Results') IS NOT NULL DROP TABLE #Results
CREATE TABLE #Results (LogDate datetime,ProcessInfo nvarchar(100),LogText nvarchar(4000))
BEGIN TRY
SELECT @begintime = GETDATE()
EXEC sp_executesql @SQL --your backup statement string
INSERT #Results
EXEC  xp_readerrorlog 0, 1, N'backed up',@databasename,@begintime
SELECT @result = LogText from #Results where ProcessInfo = 'Backup' order by logdate desc
END TRY
BEGIN CATCH
INSERT #Results
EXEC  xp_readerrorlog 0, 1, N'Backup',@databasename,@begintime
SELECT @result = LogText from #Results where ProcessInfo = 'spid'+cast(@@SPID as varchar(6)) order by logdate desc
END CATCH
PRINT @result

HTH


यह कुछ सामान्य त्रुटियों के लिए महान काम करता है, लेकिन कुछ त्रुटियां हैं जो स्पष्ट रूप से केवल ग्राहक को सीधे फेंक दी जाती हैं। Sp_readerrorlog लॉग में एक संदेश शामिल होगा जिसमें कहा जा सकता है कि "एप्लिकेशन लॉग" का संदर्भ दें, जहां मैं "एप्लिकेशन" से मानता हूं कि उनका मतलब बाहरी प्रक्रिया है जो कमांड जारी कर रहा है। एसओ लिंक
क्रोकसेक

0

आप तालिका में त्रुटि विवरण लॉग कर सकते हैं। आप एक लॉग फ़ाइल भी बना सकते हैं, लेकिन ऐसा करने के लिए CLR या xp_cmdshell की आवश्यकता हो सकती है। आप डेटाबेस मेल भी भेज सकते हैं, लेकिन इससे स्पैम समस्याएं हो सकती हैं और यह उचित लॉग नहीं है।

तालिका सबसे सरल है।

  1. त्रुटियों को संग्रहीत करने के लिए एक तालिका बनाएं
  2. एक संग्रहीत कार्यविधि बनाएँ जो त्रुटि तालिका में सम्मिलित करता है
  3. संग्रहित प्रक्रिया को कैच ब्लॉक में कॉल करें

नीचे दिए गए लिंक में जेरेमी कैडलेक का उदाहरण देखें:

http://www.mssqltips.com/sqlservertip/1152/standardized-sql-server-error-handling-and-centralized-logging/


3
समस्या त्रुटियों के साथ क्या करना है, इसके बारे में नहीं है, यह है कि उचित त्रुटि संदेश कुछ आदेशों के लिए उपलब्ध नहीं है CATCH। इसका कारण यह है केवल पिछले त्रुटि संदेश में दिया जाता है ERROR_MESSAGE()...
हारून बर्ट्रेंड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.