mkex.pe.kr 에 '허동석' 님이 작성해 주신 글을 옮겨 옵니다.
---------------------------------------------------------------------------------------------------------------------------------------
개요.
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를 이용하여 중첩 프로시저 호출로 인한 트랜잭션 처리는 데이터 무결성을 보장합니다.