SQL에서 대량 수정 작업 시 '모두 또는 아무것도' 시나리오를 구현하는 것이 종종 필요합니다. 즉, 모든 변경 사항이 통과하거나 오류 발생 시 모두 롤백됩니다. 이러한 접근 방식은 트랜잭션을 사용하여 달성됩니다. 저장 프로시저는 명시적으로 트랜잭션을 시작해야 하며(BEGIN TRANSACTION), 관련 작업을 감싸고 오류를 처리하며, 실패 시 ROLLBACK을 수행하고, 그렇지 않으면 COMMIT을 수행해야 합니다.
오류 처리를 위해 TRY...CATCH(SQL Server) 또는 EXCEPTION(PostgreSQL)와 같은 구조를 올바르게 사용하는 것을 잊지 말아야 합니다.
SQL Server에 대한 예:
CREATE PROCEDURE MassUpdate AS BEGIN BEGIN TRY BEGIN TRANSACTION; UPDATE Orders SET Status = 'Processed' WHERE Status = 'Pending'; UPDATE Inventory SET Stock = Stock - 1 WHERE ProductID IN (SELECT ProductID FROM Orders WHERE Status = 'Processed'); COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; -- 오류 로깅 THROW; END CATCH END
질문: 모든 지원되는 DBMS에서 오류 발생 시 변경 사항을 올바르게 롤백하기 위해 BEGIN TRANSACTION 및 COMMIT만 사용하면 충분합니까?
답변: 아니요, 트랜잭션 자체가 예외를 잡지 않습니다. 오류를 감지하고 명시적으로 ROLLBACK을 호출하기 위해 처리기를(TRY...CATCH 또는 유사한 방식) 사용해야 합니다. 일부 DBMS(예: auto-commit이 활성화된 MySQL)에서는 추가 설정이 필요할 수도 있습니다.
잘못된 코드 예 (SQL Server):
BEGIN TRANSACTION; UPDATE Users SET Name = 'Ivan' WHERE ID = 1; UPDATE Orders SET Amount = Amount/0 WHERE UserID = 1; -- 0으로 나누기 오류 COMMIT TRANSACTION;
이 경우 오류가 발생하면 트랜잭션이 계속 열려 있으며, 첫 번째 테이블의 변경 사항이 유지될 수 있습니다.
역사
인터넷 쇼핑몰 프로젝트에서 트랜잭션 내 오류 처리를 잊어버려 관련 데이터의 부분 손실이 발생했습니다. 주문 업데이트 중 재고 업데이트에 문제가 생길 경우 일부 변경 사항만 롤백되어 정보의 무결성이 손상되었습니다.
역사
BI 분석 프로젝트에서는 트랜잭션 제어 및 오류 잡기를 명시적으로 하지 않은 채로 보고서의 대량 재계산 절차를 도입했습니다. 결과적으로 일부 보고서는 업데이트되었고, 다른 일부는 업데이트되지 않았습니다. 최종 데이터는 불일치 상태가 되었으며, 비상 상황은 원자적 롤백으로 이어지지 않았습니다.
역사
한 회사에서는 큰 작업을 위한 트랜잭션 모드를 설정하지 않고 MySQL의 자동 커밋에만 의존했습니다. 서버 오류가 발생했을 때 일부 데이터는 이미 기록되었고, 다른 일부는 기록되지 않아 긴 복구 작업과 일부 주문 손실이 발생했습니다.