-
스프링 트랜잭션 전파(propagation)스프링/스프링 기초DB 2023. 4. 2. 14:38
트랜잭션을 하는 도중에 트랜잭션 안에서 또 다른 트랜잭션이 중첩으로 사용해야 할 경우가 있다.
이러한 것을 트랜잭션 전파(propagation)이라고 한다.
로직1 안에서 로직2이 수행되고 두 로직 다 트랜잭션을 사용한다면 로직2는 내부 트랜잭션이 된다.
이러한 경우에는 두 로직을 하나의 물리 트랜잭션으로 설정하고 그 안의 로직들은 논리 트랜잭션으로 간주한다.
여기서 중요한 것은 둘 중 어떠한 로직이라도 롤백되면 전체의 트랜잭션이 롤백되고, 모든 로직이 커밋되어야지만 커밋된다는 것이다. 외부 트랜잭션이나 내부 트랜잭션 둘 중 하나라도 롤백되면 하나만 롤백되는 것이 아니라 전체가 롤백된다는 뜻이다. 트랜잭션은 커밋을 하면 끝나기 때문에 내부 트랜잭션이 커밋되어도 commit을 하지않고 무시된다. 내부 트랜잭션이 외부 트랜잭션에 참여하기에 그렇게 되는 것이고 최종 트랜잭션까지 모두 commit되면 그때 commit이 이루어지게 된다.
전체 커밋 상황
void inner_commit() { log.info("외부 트랜잭션 시작"); TransactionStatus outer = txManger.getTransaction(new DefaultTransactionDefinition()); log.info("outer.isNewTransaction()={}", outer.isNewTransaction()); log.info("내부 트랜잭션 시작"); TransactionStatus inner = txManger.getTransaction(new DefaultTransactionAttribute()); log.info("outer.isNewTransaction()={}", inner.isNewTransaction()); // isNewTransaction이면 트랜잭션이 처음 시작되냐는 뜻 (out은 true, inner는 false) log.info("내부 트랜잭션 커밋"); txManger.commit(inner); log.info("외부 트랜잭션 커밋"); txManger.commit(outer); }
TransactionStauts에 트랜잭션 생성 결과를 반환하는데, 원래는 트랜잭션이 생성되어야하지만 위와 같은 트랜잭션 전파 상황에서는 내부 트랜잭션이 생성되지 않고 Participating in existing transaction 라고 참여한다는 로그만 뜨게 된다.
물리 트랜잭션은 외부 트랜잭션이 종료할 때까지 이어져야하며 내부 트랜잭션은 실제 커넥션에 커밋이나 롤백을 하면 안된다는 것이 중요하다.
외부만 롤백되는 상황
log.info("외부 트랜잭션 롤백"); txManger.rollback(outer);
마지막이 commit이 아니라 롤백된다면 당연히 물리 트랜잭션은 롤백될 것이다. 내부에서 커밋이 이루어진다 할지라도 실제로 커밋되는 것이 아니고 전체가 롤백 되는 것이다. 실제로 로그로 확인해봐도 commit이 된다는 로그는 찍히지 않는다.
내부만 롤백되는 상황
내부 트랜잭션을 롤백하면 실제 물리 트랜잭션은 롤백되지 않는다. 물리 트랜잭션에서는 외부 트랜잭션(신규 트랜잭션)만 커밋, 롤백을 하고 내부 트랜잭션은 외부 트랜잭션의 커넥션만 쓸 뿐이지 실제로 결과를 수행하지는 않기 때문이다.
내부 트랜잭션이 롤백되면 트랜잭션을 롤백하지 않는 대신에 트랜잭션 동기화 매니저에 "rollback-only=true" 라는 마크를 표시하고, 외부 트랜잭션은 커밋 될 시점에 "rollback-only=true" 라는 마크가 있는지 확인해서 있으면 외부 트랜잭션에서 물리 트랜잭션을 롤백하는 구조이다.
이러한 경우에는 롤백하는 것이 아니라 UnexpectedRollbackException을 던지면서 롤백한다.
개발자는 커밋을 기대하고 있는데 내부에서 롤백이 이루어져서 물리 트랜잭션이 롤백되기 때문에 런타임 예외를 던져주는 것이다.
'스프링 > 스프링 기초DB' 카테고리의 다른 글
스프링 트랜잭션 전파 - REQUIREDS_NEW (물리 트랜잭션 분리) (0) 2023.04.02 체크예외와 언체크(런타임) 예외에서의 트랜잭션 (0) 2023.04.01 트랜잭션 AOP 주의사항 - 프록시 내부 호출 (0) 2023.04.01 데이터 접근 기술 - Querydsl (0) 2023.03.28 스프링 데이터 JPA (0) 2023.03.26