REQUIRES_NEW를 사용하여, 같은 스레드에서 동기적으로 처리
REQUIRES_NEW를 사용해야 하는 이유는 다음과 같습니다.
- @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) 사용 시
- 해당 리스너 메서드는 '트랜잭션은 커밋 되었으나 종료되지 않은 상태'로 호출됨
- 즉, 트랜잭션이 커밋 된 이후 해당 리스너 메서드가 동작한다고 해도, 여전히 하나의 트랜잭션에 묶여있는 것(조회 등 가능)
- 따라서 해당 리스너 메서드 내에서 트랜잭션 작업이 이어지는 경우
- 이미 커밋된 트랜잭션 내에서의 변경 작업이기 때문에 재커밋할 수 없이 해당 작업 내용은 사라진다.
이를 해결하기 위해서는 새로운 트랜잭션을 만들어줘야 하는데,
이를 위해 해당 리스너 메서드의 트랜잭션 propagation 속성을 REQUIRES_NEW 로 설정해야 합니다.
REQUIRES_NEW 사용 시 데드락 문제
하지만 REQUIRES_NEW 를 사용하면,
기존 트랜잭션이 활성화된 상태에서 새로운 트랜잭션이 시작되며,
이로 인해 한 작업 내에서 동시에 두 개의 커넥션을 사용하게 됩니다.
HikariCP Dead lock에서 벗어나기 (이론편) 에서도 설명하고 있듯, 이런 상황에서는 데드락이 발생할 수 있습니다.
REQUIRES_NEW 사용 시 데드락 테스트에서 테스트를 진행했고, 예상과 같이 데드락이 발생한 것을 확인할 수 있었습니다.
그렇다면 REQUIRES_NEW 방식은 사용해서는 안 되는 것일까요 ?
→ 그건 아닙니다.
데드락이 발생하지 않도록 HikariCP 커넥션 풀 사이즈의 최대 개수를 늘려주면 됩니다.
공식은 다음과 같은데 (pool size = Tn x (Cm - 1) + 1) 입니다.
- Tn : 전체 스레드 개수
- Cm : 하나의 Task에서 동시에 필요한 Connection 수
그러나 위 공식에서 알 수 있듯이, REQUIRES_NEW를 사용하지 않으면, 현재 서비스상 Task에서 동시에 필요한 Connection 수는 1개이므로, Pool Size의 최소 크기는 1이면 됩니다.
그러나 REQUIRES_NEW를 사용하는 순간, 데드락 발생 방지를 위해 필요해지는 최소 커넥션의 수가 (전체 스레드 개수 + 1)이 되어,
최소 201개가 될 것입니다. (톰캣의 기본 쓰레드 풀 사이즈가 200)
'SSA > Back' 카테고리의 다른 글
| [SSA] 알림 모듈 구조 개선 및 간단한 동시성 제어 .. (2) | 2025.08.30 |
|---|---|
| [SSA] 새로운 트랜잭션을 만들면 데드락이 발생하는 것을 테스트해 보자 (0) | 2025.08.29 |
| [SSA] 500명 알림 발송 6.4초 -> 0.27초, 카프카 컨슈머 병렬 처리 적용기 (3) | 2025.08.28 |
| [SSA] 수강 기능 및 알림 기능을 한 곳에서 처리하면 발생할 수 있는 문제 (1) | 2025.07.19 |
| [SSA] 서버 SSE 기능 구현 (0) | 2025.05.11 |