본문 바로가기
Spring/DB 2편

스프링 트랜잭션 전파2 - 활용

by JHyun0302 2023. 8. 12.
728x90

커밋, 롤백

 

 

정상 커밋

 

 

 

 

@Transactional과 REQUIRED

  • REQUIRED 는 기존 트랜잭션이 없으면 새로운 트랜잭션을 만들고, 기존 트랜잭션이 있으면 참여한다.
  • @Transactional(propagation = Propagation.REQUIRED)    ==   @Transactional

 

 

 

 

 

 


서비스 계층에 트랜잭션이 없을 때 - 롤백

 

 

새로운 트랜잭션 C에서 롤백 발생

 

 

 

 

  • 이 경우 회원은 저장되지만, 회원 이력 로그는 롤백된다. 따라서 데이터 정합성에 문제가 발생
  • 둘을 하나의 트랜잭션으로 묶어서 처리해보자.

 

 

 

 

 

 


단일 트랜잭션

 

 

Repository 트랜잭션 제거, Service 트랜잭션 적용

 

 

 

 

단일 트랜잭션 사용

 

 

 

 

 

 

 


각각 트랜잭션이 필요한 상황

  • Repository & Service 모두 트랜잭션이 필요한 경우

 

트랜잭션 전파가 필요한 예시 1

 

  • 클라이언트 A : MemberService 에 트랜잭션을 남기고, MemberRepository , LogRepository 의 트랜잭션 코드를 제거해야함.
  • 그렇게 되면 클라이언트 B, C가 호출하는  MemberRepository , LogRepository 에는 트랜잭션을 적용할 수 없다.

 

 

 

 

 

 

트랜잭션 전파가 필요한 예시 2

 

  • 클라이언트 Z가 호출하는 OrderService 에서도 트랜잭션을 시작할 수 있어야 하고,
  • 클라이언트A가 호출하는 MemberService 에서도 트랜잭션을 시작할 수 있어야 한다.

 

 

 

 

 

 

 


전파 커밋

 

 

논리 트랜잭션과 물리 트랜잭션으로 구분 필요

 

 

 

실제 트랜잭션만 실제 물리 트랜잭션 시작 & 커밋

 

 

 

 

 

 

 

모든 논리 트랜잭션 커밋 성공 시 물리 트랜잭션 커밋

 

 

 

 

 

 

 


전파 롤백 

 

 

논리 트랜잭션 1개라도 롤백 시 rollbackOnly 마킹. 물리 트랜잭션 롤백!

 

 

 

 

 

 


복구 REQUIRED

 

◎ 요구 사항 : 회원 가입을 시도한 로그를 남기는데 실패하더라도 회원 가입은 유지되어야 한다.

즉, MemberRepository 논리 트랜잭션은 커밋, LogRepository 논리 트랜잭션은 롤백, 전체 물리 트랜잭션은 커밋.

 

 

 

문제 : 내부 트랜잭션에서 rollbackOnly 를 설정하기 때문에 물리 트랜잭션 롤백!

 

 

 

 

전체 흐름

 

 

 

 

 

★ 정리

  • 논리 트랜잭션 중 하나라도 롤백되면 전체 트랜잭션은 롤백된다.
  • 내부 트랜잭션이 롤백 되었는데, 외부 트랜잭션이 커밋되면 UnexpectedRollbackException 예외가 발생한다.
  • rollbackOnly 상황에서 커밋이 발생하면 UnexpectedRollbackException 예외가 발생한다

 

 

 

 

 

 

 


복구 REQUIRES_NEW

 

◎ 요구 사항 : 회원 가입을 시도한 로그를 남기는데 실패하더라도 회원 가입은 유지되어야 한다.

 

 

 

LogRepository - save() : 항상 신규 트랜잭션 생성

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(Log logMessage)

 

 

 

 

 

REQUIRES_NEW - 복구

 

  • REQUIRES_NEW 를 사용하게 되면 물리 트랜잭션 자체가 완전히 분리되어 버린다.
  • 그리고 REQUIRES_NEW 는 신규 트랜잭션이므로 rollbackOnly 표시가 되지 않는다.

 

 

 

 

 

REQUIRES_NEW 전체 흐름

 

 

 

 

 

 

★ 정리

  • 논리 트랜잭션은 하나라도 롤백되면 관련된 물리 트랜잭션은 롤백되어 버린다.
  •  REQUIRES_NEW 를 사용해서 트랜잭션을 분리해야 한다.

 

 

 

 

 

 

 

 

☆ 주의

  • REQUIRES_NEW 를 사용하면 하나의 HTTP 요청에 동시에 2개의 데이터베이스 커넥션을 사용하게 된다.
  • 성능이 중요한 곳에서는 이런 부분을 주의해서 사용해야 한다.

 

 

REQUIRES_NEW 사용하지 않고 구조 변경

 

 

반응형