Spring Framework

Spring @Transactional의 rollback 동작과정 디버깅

Junuuu 2023. 10. 30. 00:01

개요

결론적으로는 이번 디버깅을 통해 rollback의 동작과정을 알아보며 runtimeException & Error에만 롤백이 발생하는 이유와 Database 트랜잭션과 관련 없는 로직들이 Rollback 되지 않는 이유에 대해서 이해하였습니다.

 

의도적으로 예외 발생시키기

@Transactional
fun `의도적으로 예외를 발생시키기`() {
	testRepository.save(TestEntity(name = "firstSave"))
	throw RuntimeException("의도적으로 runtime Exception을 던지면 rollback이 떻게 발생할까?")
}

디버깅을 걸고 추적을 시작합니다.

 

AopUtils

invokeJoinpointUsingReflection는 AOP 메서드 호출의 일부로 리플랙션을 통해 지정된 대상 메서드를 호출하는 역할을 수행합니다.

예외가 발생하자 invokeJoinpointUsingReflection 메서드에서 해당 예외를 잡아서 ex.getTargetException을 다시 던집니다.

 

 

CglibAopProxy

해당 예외가 CglibAopProxy의 proceed 메서드로 전파되어 해당 예외가 다시 잡힙니다.

 

 

TransationAspectSupport

TransationAspectSupport 클래스는 AOP를 활용하여 트랜잭션을 처리하기 위한 기반을 제공합니다.

invokeWithinTransaction에서 해당 예외를 잡아 completeTransactionAfterThrowing메서드를 호출한 뒤 다시 예외를 던집니다.

 

invokeWithinTransaction 메서드

completeTransactionAfterThrowing메서드에서 분기문으로 transactionAttribute.rollbackOn메서드를 호출하여 해당 트랜잭션매니저에게 rollback을 호출할지 결정합니다.

 

만약 해당 분기문에서 else로 빠진다면 rollback이 아니라 commit이 호출됩니다.

 

DefaultTransactionAttribute의 rollbackOn메서드

DefaultTransactionAttribute클래스는 트랜잭션 동작을 정의하는 데 사용되며 여러 세부적인 설정(전파속성, 고립레벨, 타임아웃, readOnly, 이름)을 기본값으로 구성할 수 있습니다.

기본 정책으로 RuntimeException 또는 Error인 경우에 rollback이 발생하는 것을 확인할 수 있습니다.

 

AbstractPlatformTransactionManager의 rollback메서드가 호출됨

AbstractPlatformTransactionManager는 트랜잭션 관리를 위한 추상 클래스입니다.

다양한 데이터베이스 및 트랜잭션 관리 시스템을 추상화하여 트랜잭션의 수명 주기를 관리합니다.

 

해당 메서드에서 내부적으로 processRollback을 다시 호출합니다.

 

processRollback 메서드에서 doRollback호출

다시 내부적으로 doRollback 추상메서드를 호출합니다.

 

JpaTransactionManager에서 rollback 호출

Jpa를 활용하고 있었기 때문에 JpaTransactionManager가 호출되었습니다. (AbstractPlatformTransactionManager를 JpaTransactionManager가 구현하고 있습니다.)

내부적으로 EntityTransaction 객체를 얻어 rollback을 호출합니다.

 

TransactionImpl의 rollback 메서드가 호출

내부적으로 TransactionDriver 인터페이스를 가져와서 rollback을 호출합니다.

TransactionDriver는 TransactionCoordinator와 연결되어 물리적인 트랜잭션을 제어합니다.

JdbcResourceLocalTransactionCoordinatorImpl rollback 메서드 호출

내부적으로 jdbcResourceTransaction의 rollback 메서드가 호출됩니다.

JdbcResourceLocalTransactionCoordinatorImpl는 TransactionCoordinator interface를 구현하고 있습니다.

실제 JDBC 연결을 통해 트랜잭션을 관리합니다.

 

JdbcResourceTransaction 인터페이스의 rollback을 다시 호출합니다.

 

AbstractLogicalConnectionImplementor의 rollback 메서드

AbstractLogicalConnectionImplementor클래스가 JdbcResourceTransaction 인터페이스를 구현하고 있습니다.

Connection 인터페이스 가져와 rollback을 수행합니다.  (이를 통해  실제 Connection이 연관되어 있음을 알 수 있습니다.)

 

ProxyConnection의 rollback 메서드

Connection 인터페이스를 구현하는 추상 클래스인 ProxyConnection이 호출됩니다.

Connection 객체의 타입을 가지는 필드인 delegate의 rollback 메서드를 호출됩니다.

 

JdbcConnection의 rollback 메서드

JdbcConnection은 Connection 인터페이스를 구현하고 있는 클래스입니다.

실제 데이터베이스에 대한 connection을 담당합니다.

 

해당 rollback 메서드에서 다시 내부적으로 rollbackInternal을 호출합니다.

 

JdbcConnection의 rollbackInternal 메서드

실제 rollback 호출이 호출됩니다.

 

 

 

참고자료

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/support/AopUtils.html