인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

김채윤님의 프로필 이미지

작성한 질문수

스프링 DB 2편 - 데이터 접근 활용 기술

스프링 트랜잭션 전파6 - 내부 롤백

Rollback-only 설정 위치

작성

·

93

·

수정됨

0

평소 열심히 강의를 듣고 있는 일반적인 대학생입니다. 트랜잭션 동기화 매니저에 대해 의문사항이 많아 직접 찾아보다가 강의와 다른점이 있어 질문드립니다. 아직 부족한 학생인만큼 어느정도의 뇌피셜은 들어있습니다.. (물론 코드에 기반한)

 

질문은 가독성을 위해 음슴체를 사용한점 양해부탁드립니다..

 

결론

트랜잭션 rollback-only 은 트랜잭션 status에 있으며 해당 사실 확인은 TransactionManager에 의해 밝혀진다. 따라서, rollback-only 표시가 동기화 매니저에 있다는 설명은 수정이 필요한 것 같습니다..

-> 트랜잭션 동기화 매니저는 관련이 없는 것 아닌가 라는 생각이 듭니다..

 

그 이유는 아래와 같습니다.

 

강의제공 내용

  • 내부 롤백이 일어나면 Rollback-only 표시가 됨

  • 외부 커밋은 해당 표시를 보고 true라면 롤백

  • 해당 표시는 트랜잭션 동기화 매니저에 있음 (08:18 쯤)

 

고민하다가 의문이 든 내용

  • 트랜잭션 동기화 매니저는 쓰레드(요청)마다 적절한 트랜잭션을 찾아 주는 역할이라고 생각함 -> 트랜잭션의 상태를 관리하도록 하진 않을 것 같다는 생각이 듦 (뇌피셜)

  • 트랜잭션 매니저를 보다보니 getTransaction을 호출하면 Status를 반환함 -> 가만 생각해보면 트랜잭션 commit rollback을 트랜잭션 매니저가 하는데 상태관리도 트랜잭션 매니저가 하는게 맞지 않을까? (rollback-only 표시도 트랜잭션 매니저가 하는게 맞지 않을까?)라는 생각을 하게됨

  • 코드를 까보니 실제로 해당 메서드로 추정되는 메서드가 있음

실제 코드

JpaTransactionManger

protected void doSetRollbackOnly(DefaultTransactionStatus status) {
    JpaTransactionObject txObject = (JpaTransactionObject)status.getTransaction();
    if (status.isDebug()) {
        this.logger.debug("Setting JPA transaction on EntityManager [" + txObject.getEntityManagerHolder().getEntityManager() + "] rollback-only");
    }

    txObject.setRollbackOnly();
}

위의 코드는 내부적으로 사용하는 코드인 것 같음 (뇌피셜, 이 코드가 동작하는 것이 아닌가)

또한 아래와 같은 메서드도 존재함

public void setRollbackOnly() {
    EntityTransaction tx = this.getEntityManagerHolder().getEntityManager().getTransaction();

    if (tx.isActive()) {
        tx.setRollbackOnly();
    }

    if (this.hasConnectionHolder()) {
        this.getConnectionHolder().setRollbackOnly();
    }
}

public boolean isRollbackOnly() {
    EntityTransaction tx = this.getEntityManagerHolder().getEntityManager().getTransaction();
    return tx.getRollbackOnly();
}

아마 전자가 실제로 TransactionManager가 활용하는 코드인 것 같음 (protected라서), 후자는 외부에서 임의로 rollback-only를 설정할 때 사용하는 메서드인 것 같음 (EntityTransaction은 더 들어가보니 hibernate에서 트랜잭션을 관리하는 클래스인 것 같음)

 

DataSourceTransactionManager

해당 매니저에도 비슷한 메서드가 존재함

public void setRollbackOnly() {
	getConnectionHolder().setRollbackOnly();
}

@Override
public boolean isRollbackOnly() {
	return getConnectionHolder().isRollbackOnly();
}

 

런타임

디버깅을 돌려보며 정확히 어떤 메서드가 동작하는 지 확인해봄. 아마도 aop로  프록시 객체가 사용되는 것 같은데 aop 부분은 아직 학습하지 않아서 모르겠음..

AbstractPlatformTransactionManager -> datasourceTransactionManger의 doSetRollbackOnly 호출

 

위와 같은 코드를 보았을 때, rollback-only와 같은 트랜잭션의 상태는 트랜잭션 매니저에 의해 관리 되는 것 같고 트랜잭션 동기화 매니저는 관련이 없는 것 아닌가라는 생각이 듭니다..

답변 2

2

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 김채윤님

생각하신 내용이 맞습니다 :)

강의에서는 단순하게 설명하기 위해 "트랜잭션 동기화 매니저"라는 용어 하나로 뭉뚱그려 설명한 것이고, 코드 관점에서는 질문 주신 것처럼 결국 TransactionManager가 setRollbackOnly를 리소스 홀더에 박아두고, 이 리소스 홀더는 TransactionSynchronizationManager를 통해 쓰레드 로컬에 보관되고 있구나로 이해하시면 됩니다.

감사합니다.

0

인프런 AI 인턴님의 프로필 이미지

안녕하세요, 인프런 AI 인턴입니다.
김채윤님께서 제기하신 질문에 대해 답변드리겠습니다.

김채윤님께서 이해하신 바와 같이, 트랜잭션의 rollback-only 상태는 실제로 TransactionManager에 의해 관리됩니다. TransactionManagerdoSetRollbackOnly 메서드와 같은 내부 메서드를 통해 트랜잭션의 상태를 관리하며 rollback-only 상태를 지정할 수 있습니다.

TransactionSynchronizationManager는 주로 현재 쓰레드와 연관된 트랜잭션 리소스를 관리하고, 트랜잭션 동기화 콜백을 제공하는 역할을 합니다. 그래서 rollback-only 상태는 TransactionManager에서 관리되는 것이 맞습니다.

강의에서 트랜잭션 동기화 매니저가 rollback-only를 표시한다고 설명한 부분이 혼동을 줄 수 있을 것 같습니다. 트랜잭션의 상태(rollback 전용 표시 포함)는 TransactionManager에서 제어합니다.

따라서, 김채윤님께서 찾으신 코드와 확인하신 바가 맞습니다. JpaTransactionManagerDataSourceTransactionManagerdoSetRollbackOnly와 같은 메서드가 이러한 상태 관리를 처리합니다.

더 궁금하신 사항이 있다면 언제든지 질문해 주세요!

출처: Spring Data JPA Transactional