스프링 트랜잭션 전파 - 중첩

wangjh789·2022년 8월 22일
0

[Spring] 스프링-DB-2

목록 보기
18/21

하나의 트랜잭션이 수행중이고, 아직 끝나지 않았는데 또 다른 트랜잭션이 수행되는 경우가 있다.
먼저 시작한 트랜잭션을 외부 트랜잭션, 그 뒤의 트랜잭션을 내부 트랜잭션이라고 한다.
스프링은 이 경우 하나의 트랜잭션을 만들어준다. (default는 내부 트랜잭션이 외부 트랜잭션에 참여하는 것)

논리 트랜잭션과 물리 트랜잭션

논리 트랜잭션들은 하나의 물리 트랜잭션으로 묶이고, 트랜잭션 매니저를 통해 트랜잭션을 사용하는 단위이다.
위의 상황같은 경우 발생되는 개념이고 REQUIRED전파 옵션을 사용하는 경우에 나타난다.

원칙

  • 모든 논리 트랜잭션이 커밋되어야 물리 트랜잭션이 커밋된다.
  • 하나의 논리 트랜잭션이라도 롤백되면 물리 트랜잭션은 롤백된다.
    -> 물리 트랜잭션 매니저를 커밋해야 물리 트랜잭션이 커밋된다. 하나의 트랜잭션 매니저라도 롤백하면 물리 트랜잭션은 롤백된다.
    @Test
    void inner_commit() {
        log.info("외부 트랜잭션 시작");
        TransactionStatus outer = txManager.getTransaction(new DefaultTransactionDefinition());
        log.info("outer.isNewTransaction = {}", outer.isNewTransaction());

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

        log.info("외부 트랜잭션 커밋");
        txManager.commit(outer);
    }

status.isNewTransaction() 이라는 메서드로 외부/ 내부 트랜잭션을 구분할 수 있다.

트랜잭션 참여

  • 내부 트랜잭션이 외부 트랜잭션을 그래도 이어 받아서 따른다는 뜻이다.
  • 외부 트랜잭션의 범위가 내부 트랜잭션까지 넓어진다는 의미이다.
  • 외부 트랜잭션과 내부 트랜잭션이 하나의 물리 트랜잭션으로 묶이는 것이다.

외부 트랜잭션과 내부 트랜잭션이 하나의 물리 트랜잭션으로 묶인다고 설명했는데 어떻게 커밋을 2번 수행할까?
하나의 커넥션에 커밋은 한번만 호출할 수 있다.

외부 트랜잭션 시작
Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Acquired Connection [HikariProxyConnection@1567441485 wrapping conn0
Switching JDBC Connection [HikariProxyConnection@1567441485 wrapping conn0
outer.isNewTransaction = true

내부 트랜잭션 시작
Participating in existing transaction
inner.isNewTransaction = false
내부 트랜잭션 커밋

외부 트랜잭션 커밋
Initiating transaction commit
Committing JDBC transaction on Connection [HikariProxyConnection@1567441485 wrapping conn0:
Releasing JDBC Connection [HikariProxyConnection@1567441485 wrapping conn0:

외부 트랜잭션이 시작할 때 커넥션을 얻지만 내부 트랜잭션은 생성된 트랜잭션에 참여한다는 로그가 찍힌다.
실행 결과를 보면 외부 트랜잭션을 시작하거나 커밋할 때 DB커넥션을 통한 물리 트랜잭션을 시작하고, DB커넥션을 통해 커밋하는 것을 확인할 수 있다.
외부 트랜잭션에 의해서만 물리 트랜잭션이 동작한다. 만약 내부 트랜잭션의 커밋이 동작한다면 같은 커넥션을 쓰고 있는 외부 트랜잭션까지 이어갈 수 없다.
스프링은 처음 트랜잭션을 시작한 외부 트랜잭션이 실제 물리 트랜잭션을 관리하도록 해 트랜잭션 중복커밋 문제를 해결한다.

-> 트랜잭션에 참여한다는 뜻은 아무것도 하지 않는다는 뜻이다.

트랜잭션의 시작, 커밋or롤백을 수행할 지는 isNewTransaction()의 결과값에 따라 동작이 달라진다.

실제로 커넥션을 사용해 물리 커밋과 롤백을 수행하는 것은 신규 트랜잭션일 경우에 해당된다. 이 개념을 위해 물리 트랜잭션, 논리 트랜잭션을 나눈 것이다.

profile
기록

0개의 댓글