나는이 Insert
데이터를 공급합니다 저장 프로 시저 Table1
와 수 Column1
의 값을 Table1
과 표 2를 공급합니다 번째 저장 프로 시저를 호출합니다.
하지만 두 번째 저장 프로 시저를 다음과 같이 호출하면
Exec USPStoredProcName
다음과 같은 오류가 발생합니다.
EXECUTE 이후 트랜잭션 수는 BEGIN 및 COMMIT 문의 일치하지 않는 수를 나타냅니다. 이전 카운트 = 1, 현재 카운트 = 0.
나는 다른 질문에 대한 답변을 읽었으며 정확히 커밋 수가 엉망이되는 곳을 찾을 수 없습니다.
답변
TRY / CATCH 블록이있는 경우 가능한 원인은 트랜잭션 중단 예외를 포착하고 계속하는 것입니다. CATCH 블록에서는 항상 XACT_STATE()
적절한 중단 및 커밋 할 수없는 (두꺼운) 트랜잭션을 확인 하고 처리 해야 합니다. 호출자가 트랜잭션을 시작하고 calee가 교착 상태 (트랜잭션을 중단 함)에 도달하면 호출 수신자가 트랜잭션이 중단되었으며 ‘평상시처럼 비즈니스’를 계속해서는 안된다는 것을 호출자에게 어떻게 전달할 것인가? 가능한 유일한 방법은 예외를 다시 발생시켜 호출자가 상황을 처리하도록하는 것입니다. 중단 된 트랜잭션을 조용히 삼키고 호출자가 계속해서 원래 트랜잭션에 있다고 가정하면 신체 상해 만이 보장 할 수 있습니다 (그리고 발생하는 오류는 엔진이 자체 보호를 시도하는 방식입니다).
중첩 트랜잭션 및 예외와 함께 사용할 수있는 패턴을 보여주는 예외 처리 및 중첩 트랜잭션 을 살펴볼 것을 권장합니다 .
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
답변
나도이 문제가 있었다. 저에게 이유는 제가하고 있었기 때문입니다
return
commit
대신에
commit
return
하나의 저장 프로 시저에서.
답변
이는 일반적으로 트랜잭션이 시작되고 커밋되지 않았거나 롤백되지 않았을 때 발생합니다.
저장 프로 시저에 오류가 발생하는 경우 예외 처리없이 일부 런타임 오류로 인해 트랜잭션이 완료되지 않아 데이터베이스 테이블을 잠글 수 있습니다. 아래와 같이 예외 처리를 사용할 수 있습니다. SET XACT_ABORT
SET XACT_ABORT ON
SET NoCount ON
Begin Try
BEGIN TRANSACTION
//Insert ,update queries
COMMIT
End Try
Begin Catch
ROLLBACK
End Catch
답변
답변
저장 프로 시저가 트랜잭션을 연 후 컴파일 실패 (예 : 테이블을 찾을 수 없음, 잘못된 열 이름)가 발생하는 경우에도 발생할 수 있습니다.
Remus Rusanu가 설명한 것과 비슷한 논리를 사용하여 “worker”하나와 try / catch가있는 래퍼 하나를 2 개의 저장 프로 시저를 사용해야한다는 것을 알았습니다. 작업자 캐치는 “정상적인”실패를 처리하는 데 사용되며 래퍼 캐치는 컴파일 실패 오류를 처리하는 데 사용됩니다.
https://msdn.microsoft.com/en-us/library/ms175976.aspx
TRY… CATCH 구문의 영향을받지 않는 오류
다음 유형의 오류는 TRY… CATCH 구문과 동일한 실행 수준에서 발생할 때 CATCH 블록에서 처리되지 않습니다 .
- 구문 오류와 같은 컴파일 오류배치 실행을 방해하는 .
- 지연된 이름 확인으로 인해 컴파일 후 발생하는 개체 이름 확인 오류와 같이 문 수준 재 컴파일 중에 발생하는 오류입니다.
다른 사람이 디버깅 시간을 절약하는 데 도움이되기를 바랍니다.
답변
내 경우에는 오류가 발생되고 있던 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
답변
광범위한 디버깅 후 저에게 수정은 간단한 누락이었습니다. 롤백 후 catch의 문. 그것 없이는이 추악한 오류 메시지가 당신이 끝낼 것입니다.
begin catch
if @@trancount > 0 rollback transaction;
throw; --allows capture of useful info when an exception happens within the transaction
end catch