🍃Spring

[Spring] 트랜잭션 전파 - 1

waveofmymind 2023. 2. 5. 16:42

트랜잭션 전파란?

트랜잭션을 커넥션을 달리해서 각각 사용하는 방법이 아닌 트랜잭션 진행 중, 추가로 트랜잭션을 수행할 경우의 동작을 결정하는 것을 트랜잭션 전파라고 한다.

 

한 트랜잭션 내에서 새로운 트랜잭션이 추가로 수행될 경우

  • 처음 수행되는 트랜잭션을 상대적으로 외부 트랜잭션, 그 트랜잭션 내에서 수행되어야 하는 트랜잭션을 내부 트랜잭션이라고 한다.
  • 스프링은 이때 외부 트랜잭션과 내부 트랜잭션을 묶어서 하나의 트랜잭션으로 만들어준다.

물리 트랜잭션, 논리 트랜잭션

  • 스프링에서는 위에서 말했던 외부 트랜잭션과 내부 트랜잭션논리 트랜잭션, 그것을 하나로 묶은 트랜잭션물리 트랜잭션이라고 한다.
  • 우리가 알고 있는 DB에 커밋,롤백되는 트랜잭션을 물리 트랜잭션이라고 하고, 트랜잭션 매니저를 통해 트랜잭션을 사용하는 단위라고 생각하면 된다.
  • 위 개념은 트랜잭션 진행중 내부에서 새로운 트랜잭션이 수행되어야 할 때에만 사용되는 개념이다.
  • 물리 트랜잭션, 논리 트랜잭션은 아래와 같은 원칙을 만들기 위해 도입되었다.
    • 모든 논리 트랜잭션이 커밋되어야 물리 트랜잭션이 커밋된다.
    • 하나의 논리 트랜잭션이라도 롤백될 경우, 물리 트랜잭션은 롤백된다.
  • 모든 트랜잭션 매니저가 커밋되어야 물리 트랜잭션이 커밋될 수 있다는 것이다.

트랜잭션 전파 예제

다음과 같이 테스트 코드로 트랜잭션 전파를 알아볼 수 있다.

inner_commit()

    @Test
    void inner_commit() {
        log.info("외부 트랜잭션 시작");
        TransactionStatus outer = txManager.getTransaction(new DefaultTransactionAttribute());
        log.info("outer.isNewTransaction()={}",outer.isNewTransaction());

        log.info("내부 트랜잭션 시작");
        TransactionStatus inner = txManager.getTransaction(new DefaultTransactionAttribute());
        log.info("inner.isNewTransaction()={}", inner.isNewTransaction());
        log.info("내부 트랜잭션 커밋");
        txManager.commit(inner);

        log.info("외부 트랜잭션 커밋");
        txManager.commit(outer);
    }
  • 외부 트랜잭션이 수행중 내부 트랜잭션이 수행되는 과정이다.
  • isNewTransaction(): 해당 트랜잭션이 새로운 트랜잭션일 경우 True, 아닐경우 False를 반환한다.
    • outer.isNewTransaction()의 경우 새로운 트랜잭션이기 때문에 True
    • inner.isNewTransaction()의 경우 외부 트랜잭션에 참여한 것이기 때문에 False를 반환한다.
      • 참여라는 것은 내부 트랜잭션이 외부 트랜잭션을 이어 받는다는 뜻이다.(범위가 넓어진다.) 

실행 결과 

외부 트랜잭션 시작
Creating new transaction with name [null]: 
PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Acquired Connection [HikariProxyConnection@1943867171 wrapping conn0] for JDBC 
transaction
Switching JDBC Connection [HikariProxyConnection@1943867171 wrapping conn0] to 
manual commit
outer.isNewTransaction()=true
내부 트랜잭션 시작
Participating in existing transaction
inner.isNewTransaction()=false
내부 트랜잭션 커밋
외부 트랜잭션 커밋
Initiating transaction commit
Committing JDBC transaction on Connection [HikariProxyConnection@1943867171 
wrapping conn0]
Releasing JDBC Connection [HikariProxyConnection@1943867171 wrapping conn0] 
after transaction
  • Participating in existing transaction: 내부 트랜잭션이 시작되고, 진행되던 외부 트랜잭션에 참여하는 것을 알 수 있다.
  • 내부 트랜잭션 커밋 로그가 나오지만, txManager.commit(inner)의 로그가 나오지 않았는데 외부 트랜잭션 커밋 로그가 나왔다.
    • 한 트랜잭션당 커밋은 한번 수행되어져야 하므로, 외부 트랜잭션만 물리 트랜잭션을 시작하고, 커밋했다.
    • 내부 트랜잭션이 커밋될 경우, 외부 트랜잭션의 결과가 커밋될 수 없기 때문이다.
  • 이를 통해 처음 시작한 외부 트랜잭션이 실제 물리 트랜잭션을 관리하도록 되어있다는 것을 알 수 있다.

출처

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-2/dashboard

 

스프링 DB 2편 - 데이터 접근 활용 기술 - 인프런 | 강의

백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의 소개 | 인

www.inflearn.com