트랜잭션 전파

조승빈·2025년 1월 17일

Spring DB

목록 보기
8/8

트랜잭션 전파

이미 진행 중인 트랜잭션이 있을 때 새로운 트랜잭션을 어떻게 처리할지에 대한 전략이다.

스프링 프레임워크는 외부 트랜잭션이 존재하는 상황에서 내부 트랜잭션을 호출하면, 내부 트랜잭션은 외부 트랜잭션에 참여한다.

  1. 모든 논리 트랜잭션이 커밋되어야 물리 트랜잭션이 커밋된다.
  2. 하나의 논리 트랜잭션이라도 롤백되면 물리 트랜잭션은 롤백된다.

트랜잭션의 동작 방식

물리 트랜잭션(Physical Transaction): 데이터베이스와의 연결에서 시작되고 커밋 또는 롤백으로 끝나는 실제 트랜잭션이다.

하나의 커넥션에서 하나의 트랜잭션만 관리된다.

논리 트랜잭션(Logical Transaction): 스프링과 같은 프레임워크가 관리하는 트랜잭션 경계이다.

논리 트랜잭션은 여러 메서드 호출을 감싸며 동작한다.

코드 예시

@Transactional
public void outerMethod() {
    // 트랜잭션 시작 (물리 트랜잭션 생성)
    innerMethod();
    // 비즈니스 로직
    // outerMethod가 종료되며 트랜잭션 커밋
}

@Transactional
public void innerMethod() {
    // 이미 진행 중인 트랜잭션에 참여
    // 비즈니스 로직
}

outerMethod()가 실행되며 트랜잭션이 시작되고, 물리 트랜잭션이 생성된다.
innerMethod()가 호출되면서 별도의 물리 트랜잭션을 생성하지 않고 이미 시작된 외부 트랜잭션에 참여한다.

논리적으로 innerMethod가 끝났지만, 커밋은 실제로 일어나지 않는다. 커밋은 outerMethod가 끝날 때 한 번만 발생한다.
내부적으로 innerMethod가 오류 없이 끝나야 논리적으로 커밋 가능 상태가 된다.
물리 트랜잭션의 커밋은 외부 트랜잭션이 끝날 때 딱 한 번 발생한다.

트랜잭션에 참여한다

  • 내부 트랜잭션은 비즈니스 로직을 실행하는 동안, 외부 트랜잭션이 관리하는 커넥션을 사용한다.
  • 트랜잭션과 관련된 커밋이나 롤백 작업은 내부 트랜잭션에서 직접 처리되지 않고, 외부 트랜잭션에 의해 처리된다.
  • 비즈니스 로직 외에 트랜잭션을 관리하는 코드는 내부 트랜잭션에서는 작성하지 않으며, 모든 트랜잭션 관련 처리는 외부 트랜잭션에 의해 관리된다.

트랜잭션 롤백 시 동작 방식

외부 트랜잭션 롤백

외부 트랜잭션이 롤백되면 전체 트랜잭션이 롤백된다.

내부 트랜잭션이 커밋되었더라도 물리 트랜잭션에는 반영되지 않으며, 물리 트랜잭션이 롤백되면 전체 트랜잭션이 롤백된다.

내부 트랜잭션 롤백

내부 트랜잭션이 롤백되면, 물리 트랜잭션을 즉시 롤백하지 않는다.

대신, 롤백 전용(rollbackOnly=true) 으로 표시하여 이후 외부 트랜잭션이 커밋을 시도할 경우 롤백이 발생한다.

스프링 로그 메시지 예시:

participating transaction failed - marking existing transaction as rollback-only

외부 트랜잭션이 커밋을 시도하면 다음과 같은 예외가 발생하며 물리 트랜잭션이 롤백된다.

global transaction is marked as rollback-only but transactional code requested commit

트랜잭션 동기화 매니저가 물리 롤백을 실행하고, 트랜잭션 매니저가 UnexpectedRollbackException을 던진다.

물리 트랜잭션을 분리하는 방법 (REQUIRES_NEW)

내부 트랜잭션이 외부 트랜잭션과 분리된 별도의 물리 트랜잭션을 사용하려면 REQUIRES_NEW 옵션을 사용한다.

REQUIRES_NEW 옵션을 적용하면 내부 트랜잭션은 새로운 물리 connection을 사용하여 독립적으로 처리된다.
즉, 새로운 데이터베이스 커넥션을 별도로 생성하여 독립적인 트랜잭션을 수행한다.

이를 통해 외부 트랜잭션이 롤백되더라도 내부 트랜잭션이 영향을 받지 않도록 할 수 있다.

profile
평범

0개의 댓글