AWS Aurora Failover 대비 Spring Boot 트랜잭션 유지 및 커넥션 폐기 대응 방법

AWS Aurora를 사용하는 Spring Boot 애플리케이션에서 Writer 장애(Failover) 발생 시 트랜잭션을 유지하면서 서비스 중단을 최소화하려면 어떻게 해야 할까?
Aurora 클러스터에 연결된 상태에서 Writer 장애 발생 시 기존 커넥션이 유지되지 않으며, 트랜잭션 처리 방식은 autocommit 설정에 따라 다르게 동작한다.

이 글에서는 Aurora 장애 발생 시 트랜잭션이 어떻게 동작하는지애플리케이션에서 최적의 대응 방법을 정리한다.
✅ Aurora 장애 시 커넥션이 유지되는가?
✅ 오토 커밋(autocommit) 설정에 따라 트랜잭션 처리가 어떻게 달라지는가?
✅ Aurora 장애 대비 설정 방법 및 자동 복구를 위한 Retry 전략


1. 문제 상황

Spring Boot 애플리케이션이 HikariCP를 통해 Aurora 클러스터에 연결된 상태에서
Writer가 장애로 인해 다운되면 다음과 같은 문제가 발생할 수 있다.

🔹 일반적인 장애 발생 흐름

  1. Spring Boot 애플리케이션이 Aurora Writer와 연결된 상태에서 트랜잭션 실행 중
  2. Writer 장애 발생 → 새로운 Writer 승격
  3. 기존 Writer와 연결된 모든 커넥션이 폐기됨
  4. Spring Boot에서 CommunicationsException 또는 Transaction rolled back because connection was closed 발생
  5. Retry 없이 처리하면 기존 트랜잭션이 롤백되지 않거나, autocommit 설정에 따라 일부 데이터가 커밋됨
  6. HikariCP가 새로운 Writer로 재연결을 시도하지만, 기존 트랜잭션은 유지되지 않음
  7. Retry를 수행하면 새로운 트랜잭션을 시작하며 중복 데이터가 발생할 가능성이 있음

✅ 해결 목표:

  • Aurora 장애 시에도 애플리케이션이 정상적으로 재시도하여 데이터 무결성을 유지해야 함.
  • 커넥션 폐기 여부를 이해하고, autocommit 설정에 따른 차이를 고려해야 함.

2. Aurora 장애 발생 시 기존 커넥션 유지 여부

Spring Boot에서 Aurora 클러스터에 **클러스터 엔드포인트 (jdbc:mysql:aurora://<cluster-endpoint>)**를 사용하면,
Aurora가 자동으로 Writer를 승격해도 커넥션이 유지될 것처럼 보일 수 있다.

하지만 실제로 기존 Writer가 사라지면 해당 Writer와의 커넥션은 강제 종료되며, 기존 트랜잭션도 폐기됨.

🔹 Aurora 장애 시 커넥션 폐기 흐름

단계상태설명
1. 정상 상태✅ 유지됨Writer와의 연결이 정상적으로 유지됨
2. Writer 장애 발생❌ 기존 커넥션 종료Writer 다운으로 인해 기존 커넥션이 강제 폐기됨
3. 새로운 Writer 승격❌ 기존 트랜잭션 무효화기존 Writer에서 진행되던 트랜잭션이 유지되지 않음
4. HikariCP 재연결✅ 새로운 Writer 연결새로운 Writer와 새 커넥션이 설정됨
5. Retry 실행✅ 새로운 트랜잭션 시작기존 작업을 다시 수행함

✅ Aurora 클러스터에 연결했다고 해서 기존 Writer 장애 시 기존 커넥션이 유지되는 것은 아니다!
✅ 커넥션 풀(HikariCP)은 장애 감지 후 새로운 Writer로 자동 연결하지만, 기존 트랜잭션은 유지되지 않는다.


3. Aurora 장애 대비 설정 (Failover Mode 변경)

Aurora는 기본적으로 페일오버 발생 시 세션을 유지하지 않음.
이를 방지하려면 Failover Mode 설정을 session으로 변경해야 한다.

CALL mysql.rds_set_configuration('aurora_replica_read_consistency', 'session');

✅ 이 설정을 변경하면:

  • Failover 발생 시 기존 트랜잭션이 최대한 유지될 수 있도록 보장.
  • 하지만, Writer 장애 발생 시 기존 커넥션이 폐기되는 문제는 여전히 존재함.

4. autocommit 설정에 따른 트랜잭션 처리 차이

🔹 autocommit = true (기본값)

  • Aurora 장애 발생 전 실행된 SQL이 커밋됨.
  • Retry 시 중복 데이터가 발생할 가능성이 높음.

✅ Aurora 장애 발생 흐름 (autocommit = true)

INSERT INTO orders (id, name) VALUES (1, 'Order1'); -- ✅ 즉시 커밋됨
-- 장애 발생
-- Retry 시 동일한 INSERT 실행 → 중복 데이터 발생 가능

🔹 autocommit = false (@Transactional 사용)

  • 장애 발생 시 트랜잭션이 폐기되며 롤백될 가능성이 큼.
  • Retry 시 중복 데이터가 발생하지 않음.

✅ Aurora 장애 발생 흐름 (autocommit = false)

@Transactional
public void processData() {
myRepository.save(new DataEntity()); // 장애 발생 시 롤백됨
}

✅ 트랜잭션이 유지되지 않으므로 장애 발생 시 롤백됨.
✅ Retry 후 새로운 트랜잭션이 시작되므로 데이터 중복 문제가 없음.


5. Aurora 장애 대비 최적의 설정 방법

🔹 (1) autocommit = false 강제 적용 (@Transactional)

@Service
public class MyService {
@Transactional
public void processData() {
myRepository.save(new DataEntity()); // 장애 발생 시 롤백됨 (중복 방지)
}
}

🔹 (2) RetryTemplate을 활용한 자동 Retry

import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class MyService {
private final RetryTemplate retryTemplate;
private final MyRepository myRepository;

public MyService(RetryTemplate retryTemplate, MyRepository myRepository) {
this.retryTemplate = retryTemplate;
this.myRepository = myRepository;
}

public void processData() {
retryTemplate.execute(context -> {
saveData();
return null;
});
}

@Transactional
public void saveData() {
myRepository.save(new DataEntity()); // 장애 발생 시 롤백됨
}
}

🔹 (3) AOP를 활용한 글로벌 Retry 적용

@Aspect
@Component
public class GlobalRetryAspect {
private final RetryTemplate retryTemplate;

public GlobalRetryAspect(RetryTemplate retryTemplate) {
this.retryTemplate = retryTemplate;
}

@Around("@annotation(org.springframework.transaction.annotation.Transactional)")
public Object retryTransactionalMethods(ProceedingJoinPoint joinPoint) throws Throwable {
return retryTemplate.execute(context -> {
return joinPoint.proceed();
});
}
}

6. 결론

✅ Aurora 장애 발생 시 기존 커넥션은 폐기됨 (연결 유지 불가)
✅ 트랜잭션 유지 여부는 autocommit 설정에 따라 다르게 동작함.
✅ Retry 처리가 필수적이며, @Transactional을 통해 자동 롤백을 보장해야 함.
✅ AOP 기반 글로벌 Retry 적용으로 모든 트랜잭션에 일괄적으로 Retry 적용 가능.

🚀 Aurora 장애 발생 시 트랜잭션을 복구할 수 없으므로, 애플리케이션에서 자동으로 재시도하는 로직을 구현해야 한다!

관련 글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다