저장된 proc가 확장 성이 뛰어나고 오류 처리 기능을 포함 할 수있을 정도로 견고하게 만드는 좋은 방법은 무엇입니까?
또한 저장된 프로세스에서 여러 오류 시나리오를 처리하고 호출 앱에 의미있는 오류 정보를 반환하는 지능형 피드백 시스템을 갖추는 가장 좋은 방법은 무엇입니까?
저장된 proc가 확장 성이 뛰어나고 오류 처리 기능을 포함 할 수있을 정도로 견고하게 만드는 좋은 방법은 무엇입니까?
또한 저장된 프로세스에서 여러 오류 시나리오를 처리하고 호출 앱에 의미있는 오류 정보를 반환하는 지능형 피드백 시스템을 갖추는 가장 좋은 방법은 무엇입니까?
답변:
Alex Kuznetsov는 T-SQL TRY ... CATCH, T-SQL 트랜잭션 및 SET XACT_ABORT 설정 및 클라이언트 측 오류 처리 사용을 다루는 책인 방어 데이터베이스 프로그래밍 (8 장)에서 훌륭한 장을 가지고 있습니다. 달성해야 할 옵션에 가장 적합한 옵션을 결정하는 데 많은 도움이됩니다.
이 사이트 에서 무료 로 이용할 수 있습니다 . 나는 결코 회사와 제휴하지 않지만 그 책의 하드 카피 버전을 소유하고 있습니다.
이 주제에 대해서는 Alex가 잘 설명하는 많은 세부 사항이 있습니다.
닉의 요청에 따라 ... (이것이 모두 챕터에있는 것은 아닙니다)
스케일링 측면에서 DB 코드에 어떤 활동이 있어야하고 앱에 어떤 활동이 있어야하는지에 대해 정직해야합니다. 빠른 실행 코드가 방법 당 단일 관심사를 위해 설계로 돌아 오는 경향을 알고 계십니까?
가장 쉬운 통신 방법은 사용자 지정 오류 코드 (> 50,000)입니다. 꽤 빠릅니다. DB 코드와 앱 코드를 동기화 상태로 유지해야한다는 의미입니다. 사용자 정의 오류 코드를 사용하면 오류 메시지 문자열에 유용한 정보를 반환 할 수도 있습니다. 해당 상황에 맞는 오류 코드가 있으므로 오류 데이터 형식에 맞게 앱 코드로 파서를 작성할 수 있습니다.
또한 데이터베이스에서 논리를 다시 시도해야하는 오류 조건은 무엇입니까? X 초 후에 다시 시도하려면 앱 코드에서 처리하는 것이 좋습니다. 그래서 트랜잭션이 많이 차단되지 않습니다. DML 작업 만 즉시 다시 제출하면 SP에서 DML 작업을 반복하는 것이 더 효율적일 수 있습니다. 그러나 재 시도를 수행하려면 코드를 복제하거나 SP 계층을 추가해야 할 수 있습니다.
실제로, 그것은 현재 SQL Server의 TRY ... CATCH 논리에 가장 큰 고통입니다. 할 수는 있지만 약간의 귀찮습니다. SQL Server 2012에서 특히 개선 된 시스템 예외 (원래 오류 번호 유지)를 개선하는 방법을 찾아보십시오. 또한 FORMATMESSAGE 가 있는데 , 이는 특히 로깅 목적으로 오류 메시지를 구성하는 데 약간의 유연성을 추가합니다.
이 템플릿입니다 (오류 로깅 제거)
노트:
... 필요한 것보다 더 많은 TXN을 만들지 마십시오
하나,
CREATE PROCEDURE [Name]
AS
SET XACT_ABORT, NOCOUNT ON
DECLARE @starttrancount int
BEGIN TRY
SELECT @starttrancount = @@TRANCOUNT
IF @starttrancount = 0
BEGIN TRANSACTION
[...Perform work, call nested procedures...]
IF @starttrancount = 0
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0 AND @starttrancount = 0
ROLLBACK TRANSACTION
RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc]
END CATCH
GO
Try / Catch를 사용하지만 가능한 한 많은 정보를 수집하여 롤백 후 오류 로그에 기록합니다. 이 예에서 "LogEvent"는 발생한 이벤트의 세부 사항을 포함하는 EventLog 테이블에 쓰는 저장 프로 시저입니다. GetErrorInfo ()는 정확한 오류 메시지를 반환하는 함수 호출입니다.
오류가 발생하면 정보가 수집되고 프로시 저는 오류 처리 섹션으로 건너 뛰고 롤백을 발행합니다. 정보가 로그에 기록 된 다음 절차가 종료됩니다.
관련된 추가 프로 시저 / 함수 호출을 고려하면 약간 위에있는 것처럼 보입니다. 그러나이 방법은 문제를 디버깅 할 때 매우 유용합니다.
exec LogEvent @Process, @Database, 'blah blah blah를 삽입하려고합니다' 시작 시도 MyTable에 삽입 값을 선택하십시오 MyOtherTable에서 @rowcount = @@ ROWCOUNT를 선택하십시오. 시험 종료 -- 오류 처리 시작 캐치 @error = ERROR_NUMBER ()를 선택하십시오. @rowcount = -1, @TableAction = '삽입', @TableName = @ 데이터베이스 + '.MyTable', @AdditionalInfo = '(blah blah blah 삽입 시도 중)'+ dbo.GetErrorInfo () GOTO TableAccessError 엔드 캐치 . . . . TableAccessError : IF (@@ TRANCOUNT> 0) 롤백 @output = upper (@TableAction) 선택 + '오류-'+ 사례 (@TableAction) '업데이트'후 '업데이트'시 '삭제'후 '삭제' else @TableAction + 'ing' 끝 + '레코드'+ case (@TableAction) '선택'후 '보낸 사람' 'update'다음 'in' 'insert'다음 'into' 그렇지 않으면 '에서' 끝 + ''+ @TableName + '테이블.' @output = @output + '@@ ERROR 선택 :'+ convert (varchar (8), @ error) @output = @output + '@@ ROWCOUNT 선택 :'+ convert (varchar (8), @ rowcount) @output = @output + isnull (@AdditionalInfo, '')을 선택하십시오. exec LogEvent @Process, @Database, @Output 로그가있는 RAISERROR (@ output, 16,1) @ReturnCode = -1을 선택하십시오 GOTO THE_EXIT