본문 바로가기
DATABASE/MsSQL

[MsSQL] Exception / Throw 사용 시 주의 사항 - rollback

by DANEW 2023. 8. 5.

Intro

안녕하세요.

초보 DBA입니다.

 

얼마전 쿼리 검수를 하다가 발견한 잘못 작성된 SQL 문인데요.

논리적으로 생각해보니 이상해 보여서 테스트를 한번 진행하고 해당 내용을 남겨볼까합니다.

 

Throw와 rollback과의 관계에 대해 한번 자세히 알아보도록하죠


Exception

Throw

Throw에 대해서는 지난 포스팅에 잘 정리해놨는데요.

아래의 링크를 참고해주세요.

 

[MsSQL] Exception / Try~Catch 문 활용 -Transaction, Throw

Intro 안녕하세요 초보 DBA 다뉴입니다. 저번포스팅 Exception / Try ~ Catch문 기초에 이어서 활용하는 방법에 대해서 한번 알아보려고 하는데요. 기초에 대해 정리한 글이 궁금하신분은 아래의 글을 참

da-new.tistory.com

이렇게 Throw를 활용하여 에러를 발생시킬 수 있는데요.

 

특히 Catch 문에서 사용하는 Throw는 바로 에러를 발생시켜 실행중인 T-SQL이 실행 종료되게 됩니다.

요번에 검수하게 된 프로시저 내부 Catch 문에 Throw가 있었는데요.

아마 개발자 분이 에러가 발생할 경우 내용이 보고 싶었나봅니다.

 

근데 Throw의 위치를 곰곰히 보다보니 이상한 부분이 있었습니다. 

예제 쿼리를 한번 같이 보도록하죠.

begin try
  begin tran
    -- SQL
  commit tran
end try

begin catch
  throw;
  rollback tran
  
  select 'rollback'

end catch

Throw발생 후 rollback tran이라... 음... 뭔가 꺼림직 합니다.

에러가 발생되어 T-SQL문이 종료가 될텐데 과연 저 rollback은 실행이 될것인가?  어떻게 될것인가?

궁금했는데요.

 

결론적으로 트랜잭션이 rollback되지 못 한 상태로 있게 되었습니다.

한번 테스트를 진행해보도록 하겠습니다.

Transaction 상태에 대한 Test

Throw위치에 대해 Transaction이 어떠한 상태로 있는지 확인하고자 테스트를 진행해봤는데요.

-- Test data insert
create table XTMP_TRN_BAN (
    t_no int,
    t_cts varchar(20)
)

-- Transaction Test
begin try
  begin tran
    -- 성공 Insert
    insert into XTMP_TRN_BAN values(1, 'test1') 
    -- 실패 Insert
    insert into XTMP_TRN_BAN values(1/0, 'test2')
  commit tran
end try
begin catch
  throw;
  rollback tran
  
  select 'rollback'

end catch

테스트할 코드를 작성해봤습니다.

test1 insert 가 성공하고, test2 insert가 실패 할 텐데요.

 

실패 후 commit tran 되지 못 하고 catch문을 통해 throw를 만나게 될 것입니다. 실행 결과를 보시죠.

역시나 에러 메시지가 출력되었습니다.

Throw뒤에 있는 Select문의 출력이 나오지 않은 것을 보니 rollback과 select문은 실행이 안된 것 같은데요.

 

지금 상태에서 한번 해당 세션에서 Table을 select해보도록합니다.

역시 test1 insert만 실행이 되어있습니다.

 

다른 세션에서도 한번 select을 해보도록하겠습니다.

select을 해본결과 쿼리를 실행하는 중 이라며 진행이 되지않습니다.

쿼리를 취소해보고 한번 상태를 알아보도록하죠.

 

sp_lock명령어를 통해 해당 Transaction의 상태를 한번 찾아가봅니다.

Transaction이 실행된 세션이 56번인데요.

56번에 Table Lock이 걸려있는 모습을 확인 할 수 있습니다.

 

아직 해당 Table에 Commit도 Rollback도 되지않아서 이런 상태인 것 같네요.

56번 세션을 종료하려고 하니 이런 메시지가 출력이 되었습니다.

역시 commit, rollback 둘 중 하나의 동작으로 마무리 되어야합니다.

 

이렇게 커밋을 하거나 (commit) 하지않거나 (rollback)의 동작으로 세션을 마무리 하게 되는데요.

 

커밋을 한다면 test1의 데이터만 insert되고 종료가 될 것이고,

롤백을 한다면 test1의 데이터도 insert되지 않은 상태로 종료될 것입니다.

이렇게 부정확한 세션종료는 좋지 않아보이네요.

 

앞으로 꼭 Throw를 사용할때 주의해야 할 것 같습니다.


Outro

간단하게 Throw위치에 대해 문제가 발생할 수 있는 부분에 대해서 정리해봤는데요.

이렇게 SSMS에서 테스트를 해봤지만,

 

과연, 외부 어플리케이션에서 실행한 프로시저에 세션이 종료될때는 

커밋으로 마무리가 되었을까요? 롤백으로 마무리가 되었을까요?

이부분에 대해서는 테스트를 해보진 못했습니다.

 

하지만 어떠한 결과가 되었든 개발자가 원한 상태는 아닐 것 같다는 생각이 드네요.

 

예외처리는 프로그램의 오류를 막는 중요한 방법중 하나로

특히 Database에서 transaction을 관리하기위해 사용할 수 있는데요.

 

예외처리를 사용함으로써 다른 특이한 상황을 만드는 이러한 사용은 조심해야 할 것 같습니다.

앞으로 사용하는데 있어서 주의하였으면 합니다.

 

감사합니다.

반응형