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

이용조님의 프로필 이미지

작성한 질문수

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

스프링 트랜잭션 전파7 - REQUIRES_NEW

외부 내부 모두 신규 트랜잭션인데, 외부커넥션을 먼저 반납하는경우

22.08.16 13:55 작성

·

722

2

안녕하세요. 강의 잘 듣고 있습니다.

문득 궁금한점이 생겨서...

 

@Test
void inner_rollback_requires_new() {
log.info("외부 트랜잭션 시작");
TransactionStatus outer = txManager.getTransaction(new DefaultTransactionAttribute());
log.info("outer.isNewTransaction()={}", outer.isNewTransaction());

log.info("내부 트랜잭션 시작");
DefaultTransactionAttribute definition = new DefaultTransactionAttribute();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus inner = txManager.getTransaction(definition);
log.info("inner.isNewTransaction()={}", inner.isNewTransaction());

log.info("외부 먼저 트랜잭션 커밋");
txManager.commit(outer);

log.info("그다음 내부 트랜잭션 커밋");
txManager.commit(inner);
}

 

위와같이 외부 트랜잭션이 먼저 시작되고, 내부보다 먼저 커밋이나 롤백한 이후에

나중에 시작한 트랜잭션인 내부 트랜잭션의 커밋이라 롤백을 호출하면 IllegalStateException을 던지더라구요.

(사실 @Transactional을 이용하면 이런일이 발생하지 않게되어서 이상한 코드 인것같습니다만.., 내부트랜잭션에서 커밋이나 롤백을 누락하거나 / 멀티쓰레드 환경인데 커넥션을 파라미터로 받아서 사용한다거나 하면 겪게 될 수도 있을듯 해서요...)

사실 두 커넥션 간의 연관관계가 없다 생각했는데, 어떠한 이유로 연관이 있나보네요.

일단은 아직 고급편강의를 듣지 않았지만.. 고급편도 곧 들을 예정입니다. 고급편에서 확인할 수 있는 내용일까욤??

일단, 트랜잭션 동기화 매니저는 내부적으로 커넥션을 생성한 쓰레드로 그룹핑을 하여 관리한다고 생각하고.. 같은 쓰레드로컬 내에서 커넥션이 여러개 있을때, 먼저 생성된 커넥션이 먼저 반납되는 것 자체가 이상상태로 스프링은 취급한다 라고 생각하면 맞을까요..? 

 

질문을 다시요약해보면,

1. 트랜잭션 전파옵션을 PROPAGATION_REQUIRES_NEW로 하여 2개의 별도의 커넥션이 생성됨.

2. 한 쓰레드로 부터 생성된 커넥션은 2개인 상태.

3. 먼저생성된 커넥션의 커밋이 먼저 수행됨.

4. 나중에 생성된 커넥션의 커밋을 수행할때 illegalStateException 예외 발생.

 -> 두개의 커넥션간의 연관관계는 사실 없다고 생각드는데, 예외가 발생한것에 대해 의문점이 생깁니다!

5. 스프링은 동일한 쓰레드로 부터 여러 커넥션이 생성되었을때, 나중생성된 커넥션부터 순차적으로 커밋되지 않으면 이것 자체를 이상상태로 취급? 하는것인지 궁금합니다!

답변 3

3

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

2022. 08. 21. 16:01

안녕하세요. 이용조님

여기서 어떤 문제가 발생할지는 저도 잘 모르겠습니다.

트랜잭션은 항상 순서대로 시작하고, 역순으로 종료하셔야 합니다.

감사합니다.

김승현님의 프로필 이미지

2023. 08. 02. 12:04

그 TransactionSynchronisationManager와 연관된 문제 같습니다. outer를 닫으면서 TransactionSynchronisationManager에 어떠한 side effect 를 남기는거 같습니다.

 

제 예상으로는

outer 트랜젝션 생성 시 모종의 방식으로 현 쓰레드와 key / value 형태로 묶이는거 같습니다.

차후 inner transaction 생성 시 스택 프레임 형태로 outer 위에 트랜젝션 컨텍스트가 생성되는거 같습니다.

그 후 outer -> inner 로 컨텍스트 전환이 있는 다음,

commit(outer)를 해버리면 inner로 주 context 가 전환되었더라도 outer transaction 가 flush 됨과 동시에 현 쓰레드와 묶인 key/value 마저도 사라지는거 같습니다..

일종의 inner transaction이 좀비 프로세스가 되는 느낌...? 같습니다..

0

최승호님의 프로필 이미지

2024. 01. 16. 22:39

음 그니깐 독립 되어 있더라도 살짝만 독립된거군요

0

김승현님의 프로필 이미지

2023. 08. 01. 18:29

저게 outer 에서 inner 를 생성시켜도 transaction synchronisation을 관리하는거 같습니다..