[Spring] 트랜잭션 전파 - REQUIRES_NEW 활용하기
트랜잭션 전파
외부 트랜잭션 수행 중 내부 로직에서 새로운 트랜잭션이 수행되어야 할 때, 이때 두 트랜잭션을 어떻게 처리해야 할지 결정하는 것을 트랜잭션 전파 결정이라고 한다.
이때,기본 옵션인 REQUIRES 옵션은 수행중인 외부 트랜잭션에 내부 트랜잭션을 참가시킨다.
이렇게 되면 외부와 내부 트랜잭션을 각각 논리 트랜잭션이라고 하고, 마지막에 DB에 커밋되거나 롤백되는 하나의 트랜잭션을 물리 트랜잭션이라고 한다.
이렇게 되면 정합성을 보장받을 수 있고, 안정적인 장점이 있지만, 회원 가입을 예로 들면 이런 경우가 있을 수 있다.
- 회원 가입을 처리하는 로직(MemberService)내에는 회원 가입을 하는 로직(MemberRepository), 로그를 남기는 로직(LogRepository)이 존재한다.
- 가끔 로그를 남기는 로직이 에러가 발생해서 논리 트랜잭션이 롤백되어, 물리 트랜잭션이 롤백되어버린다.
- 로그를 남기는 로직은 에러가 발생해도 회원가입 로직이 성공했다면 회원 가입만이라도 커밋시키고 싶다.
이 경우, REQUIRES_NEW 옵션을 사용하면 된다.
REQUIRES_NEW
@Transactional(propagation=Propagation.REQUIRES_NEW)
REQUIRES_NEW 옵션은 외부 트랜잭션 수행 중 내부 트랜잭션이 실행될 경우, REQUIRES 옵션과 다르게 내부 트랜잭션을 새로운 트랜잭션으로 생성해서 로직을 실행한다.
위에서 예를 든 회원 가입 로직을 REQUIRES_NEW로 구현할 경우
- MemberService가 트랜잭션으로 수행(논리 트랜잭션 A)
- MemberRepository가 트랜잭션으로 수행(논리 트랜잭션 B)
- LogRepository가 트랜잭션으로 수행(논리 트랜잭션 C)
의 순서로 실행되는데, LogRepository에 트랜잭션 옵션을 REQUIRES_NEW로 설정하면 트랜잭션 A, B는 하나의 물리 트랜잭션으로 묶이고, 트랜잭션 C는 새로운 물리 트랜잭션으로 분리된다.
이렇게 되면 로그를 남기는 로직이 롤백되어도, 회원가입하는 로직은 정상 커밋된다.
정리
- 논리 트랜잭션은 하나라도 롤백되면 관련된 물리 트랜잭션은 전체가 롤백되어버린다.
- 이 문제를 해결하기 위해서 트랜잭션 옵션의 REQUIRES_NEW를 사용해서 트랜잭션을 분리시켜야한다.
- 주의할 점은,
- REQUIRES_NEW 옵션을 사용하게 되면 커넥션을 추가로 사용해야 하므로 성능이 떨어질 수 있다.
- 이 옵션을 사용하지 않고 해결할 수 있는 단순한 방법이 있다면, 그 방법을 선택하는 것이 좋다.
출처
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-2/dashboard
스프링 DB 2편 - 데이터 접근 활용 기술 - 인프런 | 강의
백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의 소개 | 인
www.inflearn.com