오로라 페일오버 후에도 Read-Only 오류가 발생하는 이유와 해결 방법

Amazon Aurora 클러스터에서 페일오버 진행 후 발생하는 예상치 못한 오류 메시지에 대해 알아보세요. 데이터베이스 가용성을 개선하는 방법을 소개합니다. failover 후 writer 노드에서 발생하는 read-only 오류에 대해 다룹니다.

오로라 페일오버 후에도 Read-Only 오류가 발생하는 이유와 해결 방법
Overlay Image Overlay Image
오로라 페일오버 후에도 Read-Only 오류가 발생하는 이유와 해결 방법

오로라 페일오버 후에도 Read-Only 오류 발생: 최근에 회사 시스템에 갑작스럽게 고객이 몰리는 상황이 발생하였습니다. 현재 DB 사양으로 버틸 수 없다고 판단이 되어, 더 사양이 높은 리더 인스턴스를 추가하고, 인스턴스 추가가 완료된 뒤에 failover를 진행하여 신규 인스턴스로 Write 인스턴스를 변경했습니다. 헌데 Amazon Aurora 클러스터의 페일오버를 수행한 후 예상치 못한 --read-only 오류 메시지를 접하게 되었습니다. 이는 시스템의 안정성과 가용성을 높이기 위해 페일오버를 설정한 상황에서 발생한 것이어서 당황스러웠습니다. 이번 글에서는 이 현상의 원인과 해결 방법에 대해 상세히 알아보겠습니다.

1. 발생한 문제 상황

애플리케이션에서 데이터베이스의 가용성을 높이기 위해 Aurora 클러스터의 Writer 인스턴스에 페일오버를 수행하였습니다. 페일오버 과정은 원활하게 진행되었지만, 그 후 애플리케이션에서 다음과 같은 오류 메시지가 발생하기 시작했습니다:

ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement

쓰기 작업을 시도할 때마다 이 오류가 발생하여 서비스 운영에 지장이 생겼습니다. 왜 페일오버 후에도 이런 오류가 발생하는 것일까요?

2. 문제의 원인: 엔드포인트와 DNS 캐싱

2.1 Aurora 엔드포인트의 동작 방식

Aurora 클러스터에서는 데이터베이스 인스턴스에 연결하기 위해 엔드포인트(Endpoint)를 사용합니다. 주요 엔드포인트는 다음과 같습니다:

  • 클러스터 엔드포인트(Writer Endpoint): 현재 Writer 인스턴스로 연결합니다.
  • 리더 엔드포인트(Reader Endpoint): 모든 Reader 인스턴스 중 하나에 연결합니다.
  • 인스턴스 엔드포인트(Instance Endpoint): 특정 인스턴스에 직접 연결합니다.

엔드포인트는 DNS 이름으로 제공되며, 클라이언트는 이 DNS 이름을 통해 데이터베이스 인스턴스의 IP 주소를 해석하고 연결합니다.

2.2 DNS 캐싱과 페일오버의 영향

페일오버를 수행하면 새로운 Writer 인스턴스가 지정되고, 기존의 Writer는 Reader로 전환됩니다. 이때 클러스터 엔드포인트의 DNS 레코드가 업데이트되어 새로운 Writer의 IP 주소를 가리키게 됩니다.

하지만 클라이언트 측에서 DNS 캐싱이 발생하면 문제가 생깁니다:

  • 클라이언트의 DNS 리졸버가 이전의 IP 주소를 캐싱하고 있으면, 여전히 이전의 Writer(현재는 Reader)에 연결하려고 시도합니다.
  • 이로 인해 쓰기 작업을 시도하면 해당 인스턴스는 이미 Reader이기 때문에 --read-only 오류가 발생합니다.

3. 문제 해결 방법

3.1 DNS 캐싱 기간 최소화

TTL(Time To Live) 설정 확인:

  • Aurora 엔드포인트의 DNS 레코드는 기본적으로 매우 짧은 TTL 값을 가지고 있습니다(일반적으로 5초).
  • 하지만 클라이언트나 중간 네트워크 장비에서 TTL 값을 무시하고 더 오래 캐싱할 수 있습니다.
  • 해결 방법: 클라이언트 애플리케이션과 운영 체제의 DNS 캐싱 설정을 검토하여 TTL 값을 준수하도록 설정합니다.

클라이언트 측 DNS 캐시 플러시:

  • 페일오버 후에 수동으로 DNS 캐시를 플러시하여 최신 IP 주소를 가져오도록 합니다.
  • 예시:
    • Linux: sudo systemd-resolve --flush-caches
    • Windows: ipconfig /flushdns

3.2 재시도 로직 구현

애플리케이션에서 재시도 로직 추가:

  • --read-only 오류가 발생할 경우, 일정 시간 대기 후에 DNS를 다시 조회하고 연결을 재시도합니다.
  • 예외 처리를 통해 오류 코드를 감지하고 적절한 대응을 합니다.

예시 코드 스니펫 (Java):

int retryCount = 0;
while (retryCount < MAX_RETRIES) {
    try {
        // 데이터베이스 연결 및 쓰기 작업 수행
        break; // 성공 시 루프 탈출
    } catch (SQLException e) {
        if (e.getErrorCode() == 1290) { // Read-only 오류 코드
            retryCount++;
            Thread.sleep(RETRY_DELAY);
            // DNS 캐시 무효화 (Java에서 가능하다면)
        } else {
            throw e; // 다른 오류는 재전달
        }
    }
}

3.3 연결 풀 설정 조정

연결 유효성 검사 설정:

  • 연결 풀에서 연결을 재사용하기 전에 해당 연결이 유효한지 확인합니다.
  • 오래된 연결이 사용되지 않도록 최대 생존 시간을 설정합니다.

예시 (HikariCP):

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://your-cluster-endpoint");
config.setUsername("username");
config.setPassword("password");
config.setMaximumPoolSize(10);

// 연결 테스트 쿼리 설정
config.setConnectionTestQuery("SELECT 1");
config.setConnectionTimeout(30000); // 30초
config.setMaxLifetime(1800000); // 30분
config.setValidationTimeout(5000); // 5초

3.4 Aurora 전용 드라이버 사용

AWS JDBC Driver for MySQL:

  • AWS에서는 Aurora를 위한 AWS JDBC Driver for MySQL을 제공합니다.
  • 이 드라이버는 Aurora의 페일오버를 감지하고 자동으로 새로운 Writer로 연결을 전환합니다.
  • 장점:
    • 페일오버 시 애플리케이션의 중단 시간을 최소화합니다.
    • 추가적인 코드 변경 없이도 고가용성을 지원합니다.
  • 사용 방법:
    • 기존의 MySQL JDBC 드라이버를 AWS JDBC 드라이버로 교체합니다.
    • 예시:
<!-- Maven 의존성 추가: -->
<dependency>
  <groupId>software.aws.rds</groupId>
  <artifactId>aws-mysql-jdbc</artifactId>
  <version>1.1.5</version> <!-- 버전은 최신으로 업데이트 -->
</dependency>
 // JDBC URL에 failoverStrategy 파라미터 추가:
jdbc:mysql:aws://your-cluster-endpoint:3306/dbname?failoverStrategy=failover

오로라 전용 드라이버에 대한 설명과 다운로드 링크는 오로라 공식 홈페이지에 있습니다. 링크 타고 들어가보시면 JDBC 외에도 Python과 ODBC 드라이버도 제공되고 있습니다. 이번 포스팅 내용과 밀접한 연관이 있는 “장애 조치 지원”이라는 항목에 “예” 라고 표기 되어 있고, 더 빠른 장애 조치 시간을 지원한다는 설명이 있습니다.

4. 추가 고려 사항 및 모범 사례

4.1 네트워크 인프라 검토

  • 중간 DNS 캐싱 장비 확인: 기업 내부의 DNS 서버나 프록시가 TTL을 무시하고 오래 캐싱하지 않는지 확인합니다.
  • 네트워크 팀과 협력: DNS 설정 최적화를 위해 네트워크 팀과 협업합니다.

4.2 정기적인 페일오버 테스트

  • 시나리오 테스트: 정기적으로 페일오버를 수행하여 애플리케이션이 정상적으로 동작하는지 확인합니다.
  • 모니터링 및 알림 설정: 페일오버 발생 시 빠르게 대응할 수 있도록 모니터링 시스템을 구축합니다.

4.3 클라이언트 라이브러리 업데이트

  • 최신 드라이버 사용: 데이터베이스 드라이버를 최신 버전으로 유지하여 버그 수정 및 성능 개선 사항을 반영합니다.
  • 드라이버 설정 최적화: 드라이버의 연결 속성들을 검토하여 최적의 설정을 적용합니다.

4.4 애플리케이션 아키텍처 개선

  • 읽기/쓰기 분리: 애플리케이션에서 읽기와 쓰기 작업을 분리하여 리더 엔드포인트와 Writer 엔드포인트를 적절히 활용합니다.
  • 분산 시스템 패턴 적용: 고가용성을 위해 마이크로서비스 아키텍처나 CQRS 패턴 등을 고려합니다.

결론

Aurora 클러스터에서 페일오버 후 --read-only 오류가 발생하는 주된 원인은 DNS 캐싱으로 인한 이전 Writer 인스턴스에의 연결 때문입니다. 이를 해결하기 위해서는 DNS 캐싱 설정을 검토하고, 애플리케이션에 재시도 로직을 구현하며, 연결 풀 설정을 최적화해야 합니다. 또한, AWS에서 제공하는 Aurora 전용 JDBC 드라이버를 사용하면 페일오버 상황에서 자동으로 연결을 관리하여 애플리케이션의 가용성을 높일 수 있습니다.

이번 경험을 통해 시스템의 고가용성을 달성하기 위해서는 인프라뿐만 아니라 애플리케이션 레벨에서도 세심한 고려가 필요하다는 것을 깨달았습니다. 여러분도 유사한 문제를 겪고 계시다면 이 글이 도움이 되길 바랍니다.

참조: AWS 공식 홈페이지의 관련 내용을 참고하여 작성하였습니다.

관련글

MySQL 쿼리 프로파일 설정

MySQL 쿼리 프로파일

쿼리 프로파일 수집 방법 간단 정리 MyS...

rdsrepladmin_priv_checks_user - Aurora MySQL 3.07.1 신규 계정

rdsrepladmin_priv_checks_user – Aurora

rdsrepladmin_priv_checks_user 라는 명칭의 계정...

MySQL 데이터파일 사이즈 계산

OS 접근이 불가능할 때 대략적인

OS에서 MySQL 데이터파일 사이즈 계산하기 ...

Leave a Comment