bestsource

SQL 트랜잭션 오류:현재 트랜잭션을 커밋할 수 없으며 로그 파일에 쓰는 작업을 지원할 수 없습니다.

bestsource 2023. 9. 11. 21:56
반응형

SQL 트랜잭션 오류:현재 트랜잭션을 커밋할 수 없으며 로그 파일에 쓰는 작업을 지원할 수 없습니다.

현재 트랜잭션을 커밋할없으며 로그 파일에 기록하는 작업을 지원할 수 없습니다.와 비슷한 문제가 있습니다. 하지만 후속 질문이 있습니다.

여기에 대한 답은 TRY를 사용하는...Transact-SQL에서 캐치(CATCH), 잠시 후에 다시...

내 코드(물론 상속됨)는 단순화된 형태를 갖습니다.

SET NOCOUNT ON
SET XACT_ABORT ON

CREATE TABLE #tmp

SET @transaction = 'insert_backtest_results'
BEGIN TRANSACTION @transaction

BEGIN TRY

    --do some bulk insert stuff into #tmp

END TRY

BEGIN CATCH
    ROLLBACK TRANSACTION @transaction
    SET @errorMessage = 'bulk insert error importing results for backtest '
        + CAST(@backtest_id as VARCHAR) +
        '; check backtestfiles$ directory for error files ' + 
        ' error_number: ' + CAST(ERROR_NUMBER() AS VARCHAR) + 
        ' error_message: ' + CAST(ERROR_MESSAGE() AS VARCHAR(200)) +
        ' error_severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR) +
        ' error_state ' +  CAST(ERROR_STATE() AS VARCHAR) + 
        ' error_line: ' + CAST(ERROR_LINE() AS VARCHAR)
    RAISERROR(@errorMessage, 16, 1)
    RETURN -666
END CATCH

BEGIN TRY

    EXEC usp_other_stuff_1 @whatever

    EXEC usp_other_stuff_2 @whatever

    -- a LOT of "normal" logic here... inserts, updates, etc...

END TRY

BEGIN CATCH

    ROLLBACK TRANSACTION @transaction
    SET @errorMessage = 'error importing results for backtest '
        + CAST(@backtest_id as VARCHAR) +
        ' error_number: ' + CAST(ERROR_NUMBER() AS VARCHAR) + 
        ' error_message: ' + CAST(ERROR_MESSAGE() AS VARCHAR(200)) +
        ' error_severity: ' + CAST(ERROR_SEVERITY() AS VARCHAR) +
        ' error_state ' +  CAST(ERROR_STATE() AS VARCHAR) + 
        ' error_line: ' + CAST(ERROR_LINE() AS VARCHAR)
    RAISERROR(@errorMessage, 16, 1)
    RETURN -777

END CATCH

RETURN 0

내가 가지고 있는 정보는 충분히 있다고 생각해 그냥 가지고 놀면서 스스로 알아낼 수 있는...불행히도 오류를 재현하는 것은 거의 불가능한 것으로 드러나고 있습니다.그래서 여기에 문의하는 것이 문제와 해결책에 대한 이해를 명확히 하는 데 도움이 되기를 바랍니다.

이 저장 프로시저는 간헐적으로 다음과 같은 오류를 던지는 것입니다.

backtest 9649 error_number: 3930 error_graphics에 대한 결과 가져오기 오류:현재 트랜잭션을 커밋할 수 없으며 로그 파일에 쓰는 작업을 지원할 수 없습니다.트랜잭션을 롤백합니다.error_state 1 error_line : 217

그럼 분명히 두번째 캐치블럭에서 오류가 발생하고 있습니다.

제가 'TRY 사용하기'에서 읽은 내용을 바탕으로...Transact-SQL의 캐치, 내 생각엔 예외가 던져지면 의 사용으로 인해 트랜잭션이 "종료되고 롤백되는" 현상이 발생한다고 생각합니다. 그리고 그 다음에 첫번째 줄.BEGIN CATCH맹목적으로 다시 되돌리려고 하는 겁니다

원래 개발자가 왜 활성화했는지 모르겠습니다.XACT_ABORT (보다) 더해결책은 사용하는 합니다, (하는 보다 은 은 하는 보다 XACT_STATE()에만)<>0 그게 합리적이라고 생각하십니까?내가 뭘 빼놓았나요?

또한 오류 메시지에 로그인했다는 언급은 다음과 같은 의문을 갖게 합니다.구성에 문제가 있을 가능성이 있습니까?우리가 사용하는 것은RAISEERROR()이 시나리오에서 문제에 기여하고 있습니까?오류 메시지가 암시하는 것처럼 기록이 불가능한 경우에 기록이 됩니까?

당신은 항상 확인할 필요가 있습니다.XACT_STATE(), XACT_ABORT세팅예외 처리 중첩 트랜잭션에서 TRY/CATCH 컨텍스트의 트랜잭션을 처리해야 하는 저장 프로시저용 템플릿의 예는 다음과 같습니다.

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

위의 논의에서 몇 가지 오해가 있습니다.

먼저 트랜잭션을 항상 롤백할 수 있습니다.거래 상황이 어떻든 간에따라서 XACT_STATE는 롤백 전이 아니라 COMIT 전에만 확인하면 됩니다.

코드의 오류에 관해서는 TRY 안에 트랜잭션을 넣길 원할 것입니다.그러면 캐치에서 가장 먼저 해야 할 일은 다음과 같습니다.

 IF @@TRANCOUNT > 0
      ROLLBACK TRANSACTION @transaction

그런 다음 위의 설명이 끝나면 이메일이나 필요한 것을 보낼 수 있습니다. (참고: 롤백하기 전에 이메일을 보낸다면 "할 수 없는..." 메시지를 확실히 받을 수 있습니다.write to log file" 오류가 발생했습니다.

이 문제는 작년에 발생한 문제이므로 지금쯤 해결하셨으면 좋겠습니다 :-) 레무스가 올바른 방향으로 당신을 가리켰습니다.

경험칙상...TRY는 오류가 발생하면 즉시 CATCH로 점프합니다.그런 다음 CATCH에 있을 때 XACT_STATE를 사용하여 커밋 가능 여부를 결정할 수 있습니다.그러나 항상 캐치에서 롤백(rollback)을 원하는 경우에는 상태를 전혀 확인할 필요가 없습니다.

트리거가 활성화된 테이블에서 레코드를 업데이트하는 동안 이 오류가 발생했습니다.예를 들어, 테이블 'Table1'에 트리거 'Trigger1'이 있습니다.업데이트 쿼리를 사용하여 'Table1'을 업데이트하려고 하면 동일한 오류가 발생합니다.쿼리의 레코드를 둘 이상 업데이트하는 경우 동일한 테이블에서 활성화된 경우 여러 항목의 업데이트를 지원하지 않으므로 'Trigger1'에서 이 오류가 발생하기 때문입니다.업데이트 전에 트리거 비활성화를 시도한 후 업데이트 작업을 진행했고 오류 없이 완료되었습니다.

DISABLE TRIGGER Trigger1 ON Table1;
Update query --------
Enable TRIGGER Trigger1 ON Table1;

위와 비슷한 문제가 발생하여 같은 오류 메시지를 받고 있었습니다.위의 답변들은 도움이 되었지만, 제가 필요로 했던 것은 아니었고, 사실은 조금 더 간단했습니다.

다음과 같이 구성된 저장 프로시저가 있었습니다.

SET XACT_ABORT ON

BEGIN TRY

    --Stored procedure logic
    
    BEGIN TRANSACTION
      --Transaction logic
    COMMIT TRANSACTION

    --More stored procedure logic

END TRY

BEGIN CATCH

    --Handle errors gracefully

END CATCH

TRY...CATCH저장 프로시저 로직의 오류를 처리하는 데 사용되었습니다.한되어 있으며, 이한어이며면당는당에해다지이가서e다ttdtpy당dde는eafnt,의esdfdn한이gr에만CATCH블록이지만 SQL Transaction Error 메시지와 함께 오류가 발생합니다.

이것은 다른 것을 추가함으로써 해결되었습니다.TRY...CATCH그럴만한 포장지ROLLBACK거래와THROW실수.이는 이 단계에서 발생한 모든 오류를 메인에서 우아하게 처리할 수 있음을 의미합니다.CATCH나머지 저장 프로시저에 따라 차단합니다.

SET XACT_ABORT ON

BEGIN TRY

    --Stored procedure logic
    
    BEGIN TRY
      BEGIN TRANSACTION;
        --Transaction logic
      COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH
      ROLLBACK;
      THROW;
    END CATCH

    --More stored procedure logic

END TRY

BEGIN CATCH

    --Handle errors gracefully

END CATCH

이 중 어떤 것도 도움이 되지 않았으므로 여기서 제 문제를 해결했습니다.팀 동료가 DDL 변경 사항을 모니터링하기 위해 서버 트리거를 구성했습니다.일단 비활성화하면 패키지를 설치할 수 있고 다시 활성화하면 패키지가 계속 작동합니다.

절차에서 정확히 동일한 오류가 있었습니다.이를 실행하는 사용자(우리의 경우 기술 사용자)는 임시 테이블을 만들 수 있는 권한이 충분하지 않은 것으로 드러났습니다.

EXEC sp_add 역할 구성원 'db_ddladmin', 'username_here';

속임수를 썼습니다

언급URL : https://stackoverflow.com/questions/7488149/sql-transaction-error-the-current-transaction-cannot-be-committed-and-cannot-su

반응형