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

퇴근후치맥님의 프로필 이미지
퇴근후치맥

작성한 질문수

스프링 배치

스프링 배치에서 트랜잭션 매니저 관련 질문이 있습니다.

작성

·

436

0

안녕하세요 선생님. 질문이 있습니다.

제가 알기로 배치에서는 청크 단위로 트랜잭션이 관리되는 것으로 알고 있습니다. 그렇다면 같은 트랜잭션 내에서는 같은 트랜잭션 매니저를 사용할 거라고 생각했는대요.

한 step에서 txManagerA 라는 트랜잭션 매니저를 세팅 했는데 writer 로직에서 특정 repository 을 주입 받아 쿼리 수행을 했더니 txManagerB 라는 다른 트랜잭션 매니저를 사용하게 되어 의도와는 다르게 동작합니다.

 

slave db 조회용 txManagerA, entityManagerFactoryA bean을 따로 만들었습니다. jpa 전체 설정은 @EnableJpaRepositories 어노테이션에 의해 마스터 DB용 txManagerB 로 등록되어있습니다.

엔티티, 레파지토리 패키지 경로는 마스터, 슬레이브 둘 다 같습니다.

 

트랜잭션을 별도로 연것도 아닌데 (propagation=requires_new는 사용하지 않았습니다.) 어째서 부모 트랜잭션의 txManager 를 사용하지 않는건지 잘 이해가 되지 않습니다.

 

제가 뭔가 설정을 잘못한 걸까요? 아니면 스프링의 트랜잭션 정책일까요?

답변 2

0

정수원님의 프로필 이미지
정수원
지식공유자

구체적인 코드를 보지 못해서 정확한 답변을 드리기가 쉽지 않지만 스프링 배치에서 트랜잭션 관리는 자체적으로 이루어지고 있습니다.

스프링 배치가 생성하는 트랜잭션 매니저는 기본적으로 청크 단위로 트랜잭션을 관리합니다. 이는 스프링 배치 작업의 한 청크 처리가 하나의 트랜잭션으로 묶이게 됨을 의미합니다. 하지만, 스프링 배치 작업 중에 별도의 스프링 서비스나 레파지토리를 호출할 경우 트랜잭션 처리는 그 호출된 서비스나 레파지토리의 트랜잭션 관리 정책에 따라 달라집니다.

만약 해당 서비스나 레파지토리에 별도의 트랜잭션 관리가 구성되어 있지 않다면, 이들은 스프링 배치가 관리하는 청크 단위 트랜잭션에 포함됩니다. 반면, 명시적으로 새로운 트랜잭션을 시작하도록 설정된 서비스나 레파지토리는 스프링 배치의 트랜잭션과는 별개의 트랜잭션을 가지게 됩니다.

따라서, 스프링 배치 내에서 다른 스프링 서비스나 레파지토리를 사용할 때는 해당 컴포넌트의 트랜잭션 관리 설정을 주의 깊게 확인하고 필요에 따라 조정해야 합니다.

사실 이 부분은 어떤 이유로 트랜잭션이 분리되는지의 원인이 상황에 따라 유동적이기 때문에 디버깅이나 로그를 통해서 깊게 파고 들어야 할 수도 있고 커밋이나 롤백 같은 테스트가 동반되어야 합니다

0

안녕하세요, 인프런 AI 인턴입니다.
퇴근후치맥님, 스프링 배치에서 청크 단위로 트랜잭션을 관리하는 것이 맞습니다. 각 Step에서 설정한 트랜잭션 매니저가 일관되게 사용되어야 정상입니다. 여러 EntityManagerFactories를 사용하는 경우, 각각의 JpaTransactionManager를 설정하고, @EnableJpaRepositories 어노테이션을 사용하여 각각의 EntityManagerFactory와 연결해 주시는 것이 중요합니다.

예를 들어, 마스터 DB에 접근하기 위해선 마스터 DB용 EntityManagerFactory와 트랜잭션 매니저를, 슬레이브 DB에 접근하기 위해서는 슬레이브 DB용 EntityManagerFactory와 트랜잭션 매니저를 별도로 설정하고, @EnableJpaRepositories 어노테이션의 entityManagerFactoryReftransactionManagerRef 속성을 사용하여 해당 EntityManagerFactory와 트랜잭션 매니저를 명시적으로 지정해야 할겁니다.

예시를 들면 마스터 DB용 설정에서는 다음과 같이 구성됩니다.

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = MasterEntity.class, entityManagerFactoryRef = "masterEntityManagerFactory", transactionManagerRef = "masterTransactionManager")
public class MasterDbConfiguration {
    // ... (EntityManagerFactory와 TransactionManager 빈 설정)
}

슬레이브 DB용 설정에서는 이와 유사하게 슬레이브 DB에 맞는 EntityManagerFactory와 TransactionManager를 지정해 주어야 합니다.

트랜잭션 매니저는 잘못 연결되지 않았는지, 잘못된 매니저가 주입되었는지, 혹은 @Transactional 어노테이션에서 트랜잭션 매니저가 명시적으로 지정되었는지 확인해보세요.

설정이 모두 올바른 경우에도 문제가 지속된다면 스프링의 트랜잭션 전파 정책과 관련된 부분을 더 자세히 살펴보는 것이 좋을 것 같습니다.
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.data-access.use-multiple-entity-managers

퇴근후치맥님의 프로필 이미지
퇴근후치맥

작성한 질문수

질문하기