역사적으로 SQL에서 오류 처리는 치명적인 오류 발생 후 트랜잭션 롤백으로만 제한되었습니다. 그러나 비즈니스 로직의 발전으로 인해 오류를 정확하게 기록하고, 수행된 변경 사항만 롤백하며, 프로시저 호출의 중첩 가능성이 점점 더 많이 요구되고 있습니다.
문제는 모든 DBMS에서 중첩 트랜잭션이 완전히 지원되지 않는다는 것입니다 (예: MS SQL Server에서는 이것이 실제 트랜잭션이 아니라 저장점(SAVEPOINT)의 수준에 가깝습니다) 그리고 오류 발생 시 예외가 필요한 정리를 방해할 수 있습니다. TRY/CATCH 또는 유사한 메커니즘을 사용하지 않으면 이러한 일이 발생할 수 있습니다.
해결책: TRY/CATCH (또는 유사한 구조) 및 중첩을 위한 SAVEPOINT를 사용하고, 오류 발생 시 프로시저의 동작을 설정합니다 (예: SQL Server에서 SET XACT_ABORT).
코드 예제 (MS SQL Server):
BEGIN TRY BEGIN TRANSACTION -- 작업 EXEC dbo.InnerProcedure COMMIT TRANSACTION END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION -- 오류 기록 INSERT INTO error_log VALUES (ERROR_NUMBER(), ERROR_MESSAGE(), GETDATE()) END CATCH
주요 특징:
중첩 트랜잭션에서 오류가 발생하면 실제로 모든 변경 사항이 롤백됩니까?
대부분의 DBMS에서 중첩 트랜잭션은 개별 트랜잭션이 아니라 복귀 지점(SAVEPOINT)입니다. 전체 롤백이 수행될 때 초기(바깥) 트랜잭션까지 모든 변경 사항이 롤백됩니다.
@@TRANCOUNT를 확인하지 않고 활성 트랜잭션 외부에서 ROLLBACK을 수행하면 어떻게 됩니까?
오류가 발생합니다 — 롤백할 활성 트랜잭션이 없습니다. 항상 ROLLBACK 전에 @@TRANCOUNT > 0을 확인하십시오.
TRY/CATCH에서 트리거와 커서가 작동합니까?
예, 하지만 트리거의 오류는 CATCH로의 전환을 유발하고 전체 트랜잭션을 롤백할 수 있습니다. 프로시저 본체와 호출되는 객체(프로시저, 트리거) 모두에서 오류 처리를 고려해야 합니다.
여러 개의 중첩된 프로시저가 있고, 각 프로시저가 TRY/CATCH 없이 BEGIN TRANSACTION / COMMIT을 사용하여 오류 발생 시 일부 데이터가 변경되고 일부는 그렇지 않은 경우.
장점:
단점:
모든 로직이 TRY/CATCH로 감싸져 있고, 중첩된 프로시저가 SAVEPOINT를 사용하거나 단일 외부 트랜잭션 내에서 작업하며, 모든 오류가 기록됩니다.
장점:
단점: