ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 내부 트랜잭션의 롤백과 외부 트랜잭션의 커밋
    개발/Spring 2023. 7. 6. 17:37

    하나의 물리 트랜잭션(실제 commit, rollback을 수행할 수 있는 트랜잭션) 안에 두 개의 논리 트랜잭션이 있다고 가정해보자. 이 둘은 완전히 분리되어 있는 것이 아니라 하나의 트랜잭션 안에 다른 트랜잭션이 존재하는 경우다. 신규 트랜잭션을 외부 트랜잭션이라고 하고 외부 트랜잭션 안에 있는 논리 트랜잭션을 내부 트랜잭션이라고 한다. 내부 트랜잭션 생성 시 전파(propagation) 옵션을 변경하지 않는 한(기본값 REQUIRED), 물리 트랜잭션의 커밋, 롤백은 외부 트랜잭션에서만 가능하다. 기본 동작에서는 두 트랜잭션을 모두 커밋해야 물리 트랜잭션이 커밋된다.

    신중하게 접근해야 할 예외

    어느 한 쪽이라도 예외가 발생하면 전체 커밋이 불가능한데, 외부 트랜잭션이 롤백되는 경우는 당연히 롤백이 될 것이지만, 내부 트랜잭션에서 예외가 발생하고 외부 트랜잭션에서는 커밋하고자 한다면 어떤 일이 일어날까? 다음은 테스트에서 재현해본 오류다.

    로그를 자세히 보면 "전역 트랜잭션이 rollback-only로 되어 있는데 커밋을 요청했다"는 로그가 보이고, 에러 메시지에는 비슷한 문구와 함께 UnExpectedRollbackException 예외가 확인된다. 앞서 외부 트랜잭션이 물리 트랜잭션의 커밋, 롤백이 가능하다고 했었는데, 이 말은 내부 트랜잭션에서는 커밋, 롤백이 안 된다는 의미이기도 하다. 외부 트랜잭션이 아직 끝나지도 않았는데 내부에서 멋대로 커밋, 롤백이 된다면 안 좋은 결과가 자주 나타날 것이다. 그렇다면 좋은 정책이 아니다. 돌아와서, 내부 트랜잭션에서 롤백을 진행하면, 트랜잭션 상태를 rollback-only로 설정한다. ResourceHolderSupport 클래스에서 확인할 수 있다.

    rollbackOnly = true로 세팅 이후에, 외부 트랜잭션에서 커밋을 시도하면 rollbackOnly가 true이므로 UnExpectedRollbackException예외를 발생시키게 된다. AbstractPlatformTransactionManger에서 processRollback을 수행한다. 조건문의 두 번째 조건을 따라가다 보면 rollbackOnly가 true로 되어 있다(내부 트랜잭션에서 마킹한 결과).

    댓글

Designed by Tistory.