스프링/6. 스프링 DB-2

52. 트랜잭션 전파 5

sdafdq 2023. 10. 16. 19:09

지금까지는 트랜잭션이 한몸이었는데 이번에는,

 

예를 들자면 외부 트랜잭션은 rollback이지만 내부 트랜잭은 commit인? 그 반대의 상황도.

알아보겠다.

 

그러니까, 코드상 동일한 시간선상에서 돌아간다고 하더라도, 각자 다른 트랜잭션 이다.

 

서로 각각의 물리 트랜잭션을 사용하도록.

 

 

이럴 땐 그냥 REQUIRES말고(이게 기본값임) REQUIRES_NEW 옵션을 사용하면 된다.

 

 

 

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

    log.info("내부 트랜잭션 시작");
    DefaultTransactionAttribute txDefinition = new DefaultTransactionAttribute();
    txDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);

    TransactionStatus status2 = txManager.getTransaction(txDefinition);
    log.info("내부 트랜잭션 .isNewTransaction()={}", status2.isNewTransaction());

    log.info("내부 트랜잭션 rollback");
    txManager.rollback(status2);

    log.info("외부 트랜잭션 commit");
    txManager.commit(status1);
}

첫번째 트랜 잭션 시작은 같다.

 

근데 두번째 부터는, 아예 새로운 트랜잭션으로 시작을 한다고, TransactionAttrubute에 .setPropagationBehavior()

해서 전파동작에 대한 설정을 해 줬다.

그거를 REQUIRES_NEW로.

 

그럼 완전 새 트랜잭션에서 시작이 되는거다.

로그 보면 물리 커넥션도 첫번째 트랜잭션은 conn0, 두번째 트랜잭션은 conn1을 사용한다. 당연히 프록시도 다르다.

 

그리고, isNewTransaction() 해보면 둘다 true가 나온다.

저것은 물리 트랜잭션을 책임지는, 그러니까 이 트랜잭션에서 가장 최초의 트랜잭션이냐 라고 물어보는 것이다.

 

여튼 롤백되면 롤백 되고,

 

커밋하면 커밋된다.

 

둘 사이 지장을 주는 것은 하나도 없다.

 

단 신기했던 점은, 뭐랄까 쫌 차례로? 돌아갔다.

로그를 보면,

REQUIRES_NEW인 내부 트랜잭션을 시작하면서,

Suspending current transaction, creating new transaction with name [null]

정지하고 현재 트랜잭션을, 만든다 새 트랜잭션을

이러면서 시작을 한다. 

잠깐 전의 트랜잭션을 마비시키고 차례로 돌아가는 느낌인가? 했다.

 

그럼 여러개 일 경우 어떻게 하는거지?

아니 상관없나? 

그러니까 REQUIRES_NEW가 아니라면 외부 트랜잭션 하나에 내부 트랜잭션 여러개가 추가 되는 형태이니..

뭐랄까 그냥 서로 다른 커넥션 + 트랜잭션을 사용하는? 이거는 부모 트랜잭션을 잠깐 정지하는 거랑 관계 없는 듯. 걍 서로 다른 트랜잭션 사용하는 거임.

 

외부 트랜잭션과 내부 트랜잭션은 부모자식 같은 관계로 보일수도 있겠지만, 형제끼리는 또 다를 수도 있을 듯?

 

다른 클라이언트를 통해 컨트롤러를 거쳐 다른 트랜잭션 호출하듯, 좀 남남처럼 서로 관계가 없다시피 동작한다고도 볼 수 있다.

 

REQUIRES_NEW인 내부트랜잭션들은 서로 남남이라고 보면 되는 거고, 아닌거는 좀 뭐랄까 형제? 어 하나라도 롤백이면 다 롤백이고 다같이 커밋되어야 커밋인 그런관계.

 

 

여튼, 저렇게 잠깐 외부트랜잭션을 정지 시켰다가,

REQUIRES_NEW인 내부 트랜잭션을 끝내고(rollback 또는 commit) 나면 제대로 커넥션 풀에 반환이 되고,

Resuming suspended transaction after completion of inner transaction

재시작합니다 중지되었던 트랜잭션을 내부 트랜잭션의 완료 후에

라고 로그가 나온다.

그냥 서로 다른 커넥션을 사용하는..

 

 

 

근데 아무래도..

이렇게 트랜잭션 여러 개 쓰는 것은 커넥션 풀에서 커넥션이 빠르게 고갈되니..

조심해서 써야 한다.

'스프링 > 6. 스프링 DB-2' 카테고리의 다른 글

54. 트랜잭션 전파 활용 1  (0) 2023.10.17
53. 트랜잭션 전파 6  (0) 2023.10.16
51. 트랜잭션 전파 4  (0) 2023.10.16
50. 트랜잭션 전파 3  (0) 2023.10.16
49. 스프링 트랜잭션 전파 2  (0) 2023.10.16