≣ 목차
트랜잭션 전파 속성(Propagation)이란?
작업을 하다보면 기존에 트랜잭션이 진행중일 때 추가적인 트랜잭션을 진행해야 하는 경우가 있습니다. 이미 트랜잭션이 진행중일 때 추가 트랜잭션이 어떻게 동작할지 결정하는 것을 트랜잭션 전파(propagation)옵션 입니다.
트랜잭션 전파 속성을 이해하기 전에 논리 트랜잭션과 물리 트랜잭션 개념에 대해서 아는 것이 좋습니다.
- 물리 트랜잭션: 실제 데이터베이스에 적용되는 트랜잭션을 의미하며, 커넥션을 통해 트랜잭션을 시작하고, 커넥션을 통해서 커밋, 롤백하는 단위
- 논리 트랜잭션: 스프링이 제공하는 트랜잭션 매니저를 통해 트랜잭션을 사용하는 단위
논리 트랜잭션은 호출하는 메소드 간의 관계를 정의하는 개념인 반면, 물리 트랜잭션은 실제 데이터베이스 직접 상호작용을 하는 개념입니다.
트랜잭션 전파 기본 동작(REQUIRED)
해당 상황은 트랜잭션이 진행중인데, 추가로 트랜잭션을 진행하는 상황입니다. 스프링 트랜잭션 전파 기본 동작은 여러 개의 논리 트랜잭션을 하나의 물리 트랜잭션으로 묶어 관리하고, 처음 실행한 트랜잭션이 물리 트랜잭션을 관리하여 중복 커밋 문제를 해결합니다. 예를 들어, 이미 진행 중인 트랜잭션이 있는 상황에서 추가로 트랜잭션을 실행하면, 나중에 실행된 트랜잭션이 커밋될 때 물리 트랜잭션도 함께 커밋되는 문제가 발생할 수 있습니다. 이를 방지하기 위해 스프링은 처음 실행한 트랜잭션이 물리 트랜잭션을 관리하도록 하여 데이터의 일관성을 유지합니다. 스프링이 이렇게 논리, 물리 트랜잭션 개념을 도입한 이유는 중요한 원칙을 적용하기 위해서입니다.
물리적 트랜잭션은 모든 논리적 트랜잭션이 성공적으로 커밋되었을 때만 커밋되며, 하나라도 논리적 트랜잭션이 롤백되면 물리적 트랜잭션도 롤백됩니다.
이러면 여러 케이스를 생각할 수 있습니다. 그리고
이제 처음에 실행하는 트랜잭션은 외부 트랜잭션 이라고 부르고,
나중에 실행하는 트랜잭션은 내부 트랜잭션이라고 말하겠습니다.
다양한 상황
외부 트랜잭션에서 롤백이 되는 상황
외부 트랜잭션이 물리 트랜잭션을 관리하고 앞에 설명한 원칙에 따라 해당 상황은 롤백이 됩니다.
내부 트랜잭션에서 롤백이 되는 상황 - UnexpectedRollbackException
외부 트랜잭션이 물리 트랜잭션을 관리해서 해당 상황은 커밋이 되지 않을까? 라고 생각할 수 있습니다. 하지만 원칙에 따라서 논리 트랜잭션이 하나라도 롤백이 되면 물리 트랜잭션은 롤백이 됩니다. 이렇게 동작하는 이유는 내부 트랜잭션이 롤백되면 rollbackOnly라는 속성이 설정되어 외부 트랜잭션이 커밋되더라도 물리 트랜잭션이 롤백되어 UnexpectedRollbackException이 발생합니다.
트랜잭션을 각각 분리 - REQUIRES_NEW
REQUIRES_NEW는 외부 트랜잭션과 내부 트랜잭션을 두 개의 독립적인 물리 트랜잭션으로 분리하여 각각 완전히 별도로 실행합니다. 새로운 물리 트랜잭션이 생성되기 때문에 추가적인 커넥션이 사용됩니다.
두 개는 서로 다른 물리 트랜잭션이므로, 당연히 논리 트랜잭션이 다른 논리 트랜잭션 결과에 영향을 주지 않는다.
동작 설명
로직 1이 실행되지만, 로직2에서 커밋 또는 롤백이 발생할 때까지 로직1은 대기 상태에 놓입니다. 로직2가 작업을 완료하면, 대기 중이던 로직1이 다시 작업을 수행하게 됩니다.
트랜잭션 전파 옵션 요약
의미 | 기존 트랜잭션 O | 기존 트랜잭션 X | |
REQUIRED | 기존 트랜잭션이 없으면 생성하고, 있으면 참여(기본 ) | 기존 트랜잭션에 참여 | 새로운 트랜잭션을 생성 |
REQUIRES_NEW | 항상 새로운 트랜잭션을 생성 | 새로운 트랜잭션을 생성 | 새로운 트랜잭션을 생성 |
SUPPORT | 기존 트랜잭션이 없으면, 없는대로 진행하고, 있으면 참여 | 기존 트랜잭션에 참여 | 트랜잭션 없이 진행 |
NOT_SUPPORT | 트랜잭션을 지원하지 않음 | 트랜잭션 없이 진행 ( 기존 트랜잭션은 보류 ) |
트랜잭션 없이 진행 |
MANDATORY | 트랜잭션이 무조건 있어야 함 | 기존 트랜잭션에 참여 | IllegalTransactionStateException 예외 발생 |
NEVER | 기존 트랜잭션도 허용하지 않는 강한 부정 | IllegalTransactionStateException 예외 발생 | 트랜잭션 없이 진행 |
NESTED | 중첩 트랜잭션 생성 | 중첩 트랜잭션 생성 | 새로운 트랜잭션을 생성 |
참고
스프링 DB 2편 - 데이터 접근 활용 기술(김영한)
'Spring' 카테고리의 다른 글
[Spring] 스프링 프록시 팩토리 간단 정리 (0) | 2024.09.19 |
---|---|
[Spring] Spring Security 6.x버전 달라진 사항 (0) | 2024.09.15 |
[Spring] @Transactional 정리 (1) | 2024.08.28 |
[Spring + DB] 스프링의 DB 예외 추상화 - ExceptionTranslator (0) | 2024.08.15 |
[Spring+DB] 트랜잭션 추상화 및 동기화- TransactionManager (0) | 2024.08.10 |