동적 SQL 백업 명령에 try / catch를 사용할 때 오류 세부 사항을 기록하는 방법


10

try catch 및 dynamic sql을 사용하는 저장 프로 시저 내에서 백업 명령을 실행할 때 백업 명령을 직접 실행하는 것과 비교할 때 오류 메시지가 매우 일반적입니다.

SP 내에서 시도 / 잡기 :

    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 Server 데이터베이스 오류 : "H : \ FolderName \ Filename.bak :"파일에서 복구 할 수없는 I / O 오류가 발생했습니다. 112 (디스크에 공간이 부족합니다.)

저장 프로 시저 내에서 이러한 세부 정보를 변수로 포착하는 방법이 있습니까? 세부 정보가 메시지 채널을 통해 전달되는 것 같지만 SP 내에서 사용할 수 있기를 바랍니다.


:이 참조 할 수 있습니다 stackoverflow.com/questions/5966670/...
8킬로바이트

답변:


13

BACKUP DATABASE오류가 발생, 실제로 두 가지를 생성합니다. 불행히도 TRY/CATCH첫 번째 오류를 캡처 할 수 없습니다. 두 번째 오류 만 캡처합니다.

나는 실패한 백업을 통해 백업을 자동화하는 것입니다 뒤에 가장 좋은 건 진짜 이유를 캡처하는 의심 SQLCMD (과 -o출력을 파일로 보내), SSIS는, C #을, 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 Server <2012에서는 오류를 직접 발생시킬 수 없지만 SQL Server 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 내에서 작동하지 않는다고 말하고 있습니까?
crokusek 2016 년

@crokusek 나는 하나의 변형을 시도했고 결과는 비어있었습니다. 나는 오늘 또 다른 기회를 줄 것이다.
Aaron Bertrand

오류가없는 경우 LastErrorMessage ()는 세션에서 이전 오류의 결과를 가져 옵니까? 그런 다음 마지막 두 exec가 스크립트로 실행되는 경우 첫 번째 exec는 try / catch 및 catch 내에서 랩핑되어 변수를 설정 한 다음 다시 던질 수 있습니다. 그런 다음 변수가 설정된 경우에만 LastError가 호출됩니다. 다시 던지기가 스크립팅 컨텍스트에서 일반적으로 사실이라고 생각하는 두 번째 호출을 건너 뛰지 않는다고 가정합니다. 올바르게 이해하면 SP에 모두 배치 할 수 없으므로이 접근법을 결국에는 사용할 수 없습니다. 그래도 고마워!
crokusek

2

글쎄, 이것은 오래된 스레드라는 것을 알고 있으며, 제안하려고하는 것이 복잡한 해킹이라는 것을 알고 있지만 누군가를 도울 수있는 경우를 대비하여 다음과 같습니다.이 백업 오류가 기록되므로 xp_readerrorlog를 catch에서 사용할 수 있습니다 관련 메시지 (오류 또는 정보)에 대한 로그를 스크랩하기 위해 차단합니다. xp_readerrorlog 매개 변수를 검색 할 수는 있지만 간단히 말하면이 경우 유용한 검색 문자열과 시작 시간 필터를 지정할 수 있습니다. 이것이 재시도 논리에 도움이되는지 확실하지 않지만 로깅을 위해 정보 또는 오류를 캡처하기 위해 다음과 같은 것을 생각해 냈습니다.

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 로그에는 "application log"를 참조하는 메시지가 포함됩니다. 여기서 "application"은 명령을 실행하는 외부 프로세스를 의미합니다. SO Link
crokusek

0

오류 세부 사항을 테이블에 로그 할 수 있습니다. 로그 파일을 만들 수도 있지만 그렇게하려면 CLR 또는 xp_cmdshell이 ​​필요할 수 있습니다. 데이터베이스 메일을 보낼 수도 있지만 스팸 문제가 발생할 수 있으며 올바른 로그가 아닙니다.

테이블이 가장 간단합니다.

  1. 오류를 저장하기위한 테이블 만들기
  2. 오류 테이블에 삽입하는 스토어드 프로 시저 작성
  3. catch 블록에서 저장 프로 시저를 호출하십시오.

아래 링크에서 제공되는 Jeremy Kadlec의 예를 살펴보십시오.

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


3
문제는 오류로 무엇을해야하는지에 관한 것이 아니라의 일부 명령에 적절한 오류 메시지를 사용할 수 없다는 것 CATCH입니다. 마지막 오류 메시지 만 반환 되기 때문 입니다 ERROR_MESSAGE().
Aaron Bertrand
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.