작성
·
762
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. 스프링은 동일한 쓰레드로 부터 여러 커넥션이 생성되었을때, 나중생성된 커넥션부터 순차적으로 커밋되지 않으면 이것 자체를 이상상태로 취급? 하는것인지 궁금합니다!
그 TransactionSynchronisationManager와 연관된 문제 같습니다. outer를 닫으면서 TransactionSynchronisationManager에 어떠한 side effect 를 남기는거 같습니다.
제 예상으로는
outer 트랜젝션 생성 시 모종의 방식으로 현 쓰레드와 key / value 형태로 묶이는거 같습니다.
차후 inner transaction 생성 시 스택 프레임 형태로 outer 위에 트랜젝션 컨텍스트가 생성되는거 같습니다.
그 후 outer -> inner 로 컨텍스트 전환이 있는 다음,
commit(outer)를 해버리면 inner로 주 context 가 전환되었더라도 outer transaction 가 flush 됨과 동시에 현 쓰레드와 묶인 key/value 마저도 사라지는거 같습니다..
일종의 inner transaction이 좀비 프로세스가 되는 느낌...? 같습니다..