DB

[MySQL] (연결최적화4️⃣) 트랜잭션 전파 방식과 커넥션 이슈 분석

인생아 2025. 7. 18. 22:38
반응형

Spring 기반 애플리케이션에서 MySQL과 트랜잭션을 다룰 때 종종 발생하는 문제가 있다.
바로 트랜잭션 전파(propagation) 방식에 따라 커넥션이 예상치 못하게 생성되거나 공유되지 않는 현상이다.
이 글에서는 전파 유형별 동작 원리와 실무에서 자주 발생하는 커넥션 이슈를 정리한다.

🔄 트랜잭션 전파(Propagation)란?

트랜잭션 전파는 메서드 호출 시 기존 트랜잭션이 있을 때의 처리 방식을 결정하는 속성이다.
Spring에서는 @Transactional(propagation = ...)으로 설정한다.

주요 전파 유형 요약

전파 유형 설명
REQUIRED 기존 트랜잭션이 있으면 참여, 없으면 새로 생성 (기본값)
REQUIRES_NEW 항상 새 트랜잭션 시작. 기존 트랜잭션은 일시 정지
NESTED 기존 트랜잭션에 중첩되어 savepoint로 동작
SUPPORTS 있으면 참여, 없으면 트랜잭션 없이 실행
NOT_SUPPORTED 트랜잭션 없이 실행. 기존 트랜잭션은 정지
MANDATORY 반드시 트랜잭션 존재해야 실행
NEVER 트랜잭션이 있으면 예외 발생
반응형

⚠️ 전파 방식과 커넥션의 관계

Spring 트랜잭션은 커넥션과 밀접하게 연결되어 있다.
트랜잭션 범위 안에서 커넥션이 유지되며, 전파 방식에 따라 커넥션 공유 여부가 달라진다.

예시 1: REQUIRES_NEW는 새 커넥션 생성

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveAuditLog() {
  // 별도 트랜잭션 → 별도 커넥션 사용
}
  • 기존 커넥션은 중지되고, 새로운 커넥션이 풀에서 할당됨
  • 동시에 여러 REQUIRES_NEW 호출 시 커넥션 풀이 고갈될 수 있음

예시 2: REQUIRED는 커넥션 공유

@Transactional
public void saveMainAndDetail() {
  saveMain();     // REQUIRED
  saveDetail();   // REQUIRED → 같은 커넥션
}
  • 같은 트랜잭션 범위에서는 커넥션을 재사용
  • 예외 발생 시 전체 롤백 처리 가능

🧪 실무 커넥션 이슈 시나리오

시나리오 1: 커넥션 풀 고갈

  • 여러 서비스가 동시에 REQUIRES_NEW로 호출되면
  • 커넥션을 계속 새로 빌려오게 되고
  • Timeout waiting for connection 예외 발생

✅ 해결 방법
→ maximumPoolSize 증가 + 꼭 필요한 경우에만 REQUIRES_NEW 사용

시나리오 2: 트랜잭션 누락

  • 서비스 A는 트랜잭션 O
  • 서비스 B는 트랜잭션 없음
  • 서비스 A → B 호출 시 B에서 DB 커넥션이 공유되지 않아 예외 발생 가능

✅ 해결 방법
→ 하위 서비스에도 @Transactional 명시하여 전파 가능하도록 설정

반응형

🔍 전파 방식 선택 가이드


 

상황 추천 전파 방식 이유
여러 저장 로직을 하나의 트랜잭션으로
묶을 때
REQUIRED 커넥션 공유, 전체 롤백 가능
로깅, 알림 등 실패해도 되는 부가 작업 REQUIRES_NEW 메인 트랜잭션과 분리됨
내부 단계별 롤백을 나누고 싶을 때 NESTED savepoint 활용 가능
(단, MySQL은 JDBC 드라이버 지원 여부 확인)
 

✅ 커넥션 절약을 위한 팁

  • REQUIRES_NEW 남발 금지 → 불필요한 커넥션 증가
  • NOT_SUPPORTED는 트랜잭션 격리 필요 없는 작업에만 사용
  • 하나의 HTTP 요청 처리에서 커넥션 수가 늘어나는 구조는 지양
  • 커넥션 풀 수치를 항상 전파 방식과 함께 고려

📘 공식 문서 참고

반응형