콘텐츠로 건너뛰기
문제 현상
- Tasklet 내부 반복 로직 중 일부 예외 발생 시 커넥션 반환이 이루어지지 않아 HikariCP 커넥션 풀 고갈 발생
- 이로 인해 다음 반복 구간부터 커넥션 할당 실패, Job 전체 장애 또는 재시작 필요
원인 분석
- 예외 발생 시
catch
블록에서 contribution.setExitStatus(ExitStatus.FAILED)
로만 처리하고, throw
하지 않으면 rollback은 수행되지만 커넥션이 반환되지 않을 수 있음
- 특히 직접 JDBC 커넥션을 받아 사용하는 경우 수동 반환 필수
해결 방법
- 개별 항목마다 트랜잭션 분리 (TransactionTemplate 활용)
for (Map.Entry<String, DataFeedDTO> entry : dataFeedDTOs.entrySet()) {
transactionTemplate.execute(status -> {
try {
// 처리 로직
} catch (Exception e) {
log.error("처리 중 오류 발생: {}", entry.getKey());
status.setRollbackOnly(); // 해당 항목만 롤백
} return null; });
}
- catch 블록에서 명시적 커넥션 반환
try {
// 커넥션 사용하는 로직
} catch (Exception e) {
contribution.setExitStatus(ExitStatus.FAILED);
DataSourceUtils.releaseConnection(connection, dataSource); //
수동 반환 return
RepeatStatus.FINISHED;
}
- TransactionTemplate 선언 방식
@Autowired @Qualifier("yourTransactionManager")
private PlatformTransactionManager transactionManager;
private final TransactionTemplate transactionTemplate;
@PostConstruct public void init() {
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
적용 후 기대 효과
- 개별 항목 단위 롤백이 가능해져서 전체 작업 중단 없이 실패 항목만 건너뜀
- 수동 커넥션 반환을 통해 HikariCP 커넥션 누수 방지
- 안정적인 트랜잭션 관리 및 자원 회수 보장