관리 메뉴

Data Modeling Evangelist Kaien Kim's Blog

[SQLServer] TRY..CATCH를 이용한 중첩 트랜잭션 예외처리. 본문

DATA/SQLServer

[SQLServer] TRY..CATCH를 이용한 중첩 트랜잭션 예외처리.

2010. 8. 31. 10:17
TRY..CATCH를 이용한 중첩 트랜잭션 예외처리.  

개요.

TRY .. CATCH 구문 내에서의 트랙잭션 처리에 대해 어떻게 구현되는지 알아보는 것과 트랜잭션으로 처리하는 프로시저 내에서

다시 트랜잭션으로 처리하는 프로시저를 호출 시 제대로 작동하는지 확인하는 것이 이 문서의 목적입니다.


테스트 샘플.


테스트 샘플은 분모를 파라미터로 받아서 0을 제외한 값은 에러가 나지 않고 0인 값은 에러가 나는 예제입니다.



1. 테스트 테이블 생성

CREATE TABLE TryTest
(
       id1 int,
       id2 int
)

2. 부모 프로시저 작성.

CREATE PROCEDURE ParentTest

(
       @bunmo int
)
AS

BEGIN
SET NOCOUNT ON;

       BEGIN TRY

             BEGIN TRAN ParentTest1

                    INSERT INTO TryTest VALUES(2,1)

                    EXEC ChildTest @bunmo

                    PRINT('ParentTest')

                    INSERT INTO TryTest VALUES(2,2)

             COMMIT TRAN ParentTest1

       END TRY
       BEGIN CATCH

             ROLLBACK TRAN ParentTest1
             PRINT('Parent ERROR')

       END CATCH

       SET NOCOUNT OFF;

END 

3. 자식 프로시저 작성.

CREATE PROCEDURE ChildTest ( 
       @bunmo int
)

AS

BEGIN

SET NOCOUNT ON;

       BEGIN TRY

             BEGIN TRAN ChildTest1
                    INSERT INTO TryTest VALUES(1,1)
                    PRINT(1/@bunmo)
                    INSERT INTO TryTest VALUES(1,2)
                    COMMIT TRAN ChildTest1
       END TRY

       BEGIN CATCH
             ROLLBACK TRAN ChildTest1
             PRINT('Child ERROR')
       END CATCH

       SET NOCOUNT OFF;

END

4. 실행.

4.1. 에러 발생 시

EXEC ParentTest 0

실행 결과 : Parent ERROR
데이터 결과 : 데이터 쌓이지 않음.

흐름.

ParentTest
프로시저에 2,1 데이터를 등록 ChildTest 프로시저를 실행합니다.
ChildTest 내에서 1,1 인서트 0으로 나누려 했기 때문에 CATCH 구문으로 이동하여 롤백합니다.
'Child ERROR'
출력하지 않는 이유는 ROLLBACK TRAN ChildTest1 시점에 프로시저를 벗어나기 때문입니다.
다시 ParentTest으로 넘어온 ParentTest 출력하지 않고
부모에서 ROLLBACK 되었기 때문에
바로 CATCH 구문으로 이동합니다.
롤백 처리한 'Parent ERROR' 출력합니다.
결국 Parent, Child 모두 롤백되므로 인서트된 데이터들은 없습니다.

4.2. 정상 실행 시

EXEC ParentTest 1

실행 결과 :

1

ParentTest

데이터 결과 : 4건 등록됨.
2         1
1         1
1         2
2         2


흐름.
ParentTest 프로시저에 2,1 데이터를 등록 ChildTest 프로시저를 실행합니다.
ChildTest 내에서 1,1 인서트 1 나누려 했기 때문에 CATCH 구문으로 이동하지 않고 1,2 인서트 합니다.
트랜잭션을 COMMIT 시킨 Parent 돌아와서 ParentTest’ 출력 2,2 인서트하고 COMMIT 시킵니다.
 

5. 결론

TRY..CATCH 이용하여 중첩 프로시저 호출로 인한 트랜잭션 처리는 데이터 무결성을 보장합니다.

출처 : http://www.mobilepro.pe.kr/trackback_post_122.aspx