문제 요약
Spring Batch Tasklet 내부에서 슬레이브(readOnly) DataSource를 통해 조회를 수행 중 예외 발생 시, PlatformTransactionManager의 rollback 처리 후 커넥션이 반환되지 않는 문제가 발생하였습니다.
원인 분석
- Tasklet 내부 로직이
try-catch
만으로 예외를 흡수하고throw
를 하지 않음 - TransactionTemplate rollback 발생 시 커넥션이 반환되지 않고 held 상태로 유지됨
- Slave DataSource는
autoCommit=true
라 해도 rollback 발생 시 Connection 종료가 보장되지 않음
개선 방안
- 조회 전용 커넥션 로직은
try-catch-finally
구조로 명시적으로null 처리 or close
- 예외 발생 시
contribution.setExitStatus(ExitStatus.FAILED)
명시 - 중요: 커넥션 조회만 수행할 경우 트랜잭션 적용 대상인지 재검토
for (Map.Entry<String, DTO> entry : DTOs.entrySet()) {
transactionTemplate.execute(status -> {
try {
...
} catch (Exception e) {
log.error(...);
status.setRollbackOnly(); //
해당 항목만 롤백
}
return null;
});
}
또는 명시적 반환 방식:
try {
// 작업 수행
} catch (Exception e) {
log.error("예외 발생", e);
contribution.setExitStatus(ExitStatus.FAILED);
//
커넥션 명시적 반환 유도
DataSourceUtils.releaseConnection(connection, dataSource);
return RepeatStatus.FINISHED;
}