트랜잭션은 데이터베이스에서 하나의 논리적인 작업 단위로 처리해야 하는 연산들의 묶음입니다. 예를 들어 주문 생성과 재고 차감이 하나의 작업이라면 둘 다 성공하거나 둘 다 실패해야 데이터가 어긋나지 않습니다.
트랜잭션의 핵심 특징은 ACID로 설명합니다.
- Atomicity, 원자성: 트랜잭션의 작업은 모두 성공하거나 모두 롤백되어야 합니다.
- Consistency, 일관성: 트랜잭션 전후에 제약조건과 비즈니스 규칙을 만족하는 유효한 상태를 유지해야 합니다.
- Isolation, 격리성: 동시에 실행되는 트랜잭션이 서로의 중간 상태에 부적절하게 영향을 주지 않아야 합니다. 어느 정도 격리할지는 격리 수준으로 조절합니다.
- Durability, 지속성(영존성): 커밋된 결과는 장애가 발생하더라도 보존되어야 합니다.
DBMS는 잠금, MVCC, Undo Log, Redo Log 같은 기능으로 이러한 성질을 지원합니다. 다만 트랜잭션을 너무 크게 잡으면 잠금 보유 시간과 충돌 가능성이 커지고, 너무 작게 나누면 하나의 비즈니스 작업에 필요한 원자성을 잃을 수 있으므로 업무 단위에 맞게 경계를 설정해야 합니다.
Spring의
@Transactional을 붙이면 ACID가 모두 자동으로 보장되나요?
@Transactional은TransactionManager를 통해 트랜잭션의 시작, 커밋, 롤백 경계를 관리합니다. 실제 원자성·격리성·지속성은 사용하는 DBMS와 스토리지 엔진, 격리 수준 및 설정의 영향을 받으며, 비즈니스 규칙에 대한 일관성은 애플리케이션도 올바르게 구현해야 합니다.
원자성과 일관성은 어떤 차이가 있나요?
원자성은 트랜잭션에 포함된 작업을 전부 반영하거나 전부 취소하는 실행 단위의 성질입니다. 일관성은 그 결과가 데이터베이스 제약조건과 비즈니스 규칙을 만족하는 유효한 상태여야 한다는 성질입니다.
트랜잭션 범위를 가능한 크게 잡으면 더 안전한가요?
반드시 그렇지는 않습니다. 긴 트랜잭션은 커넥션과 잠금을 오래 점유하여 동시성을 낮추고 교착 상태 가능성을 높입니다. 외부 API 호출처럼 오래 걸리는 작업은 가능하면 DB 트랜잭션 밖으로 분리하되, 전체 업무의 일관성은 보상 트랜잭션이나 이벤트 처리 등을 함께 고려해야 합니다.