MeetBack 2026.08.24 6 min read

MySQL 8 GTID·TLS Primary Replica 구축과 수동 Failover 선택

MySQL 8.0.46 두 대에 GTID·TLS 복제를 구성했다. 비밀번호 길이 오류와 주소 변경 뒤 재접속을 확인하고, 데이터 복제·쓰기 차단과 수동 전환 범위를 정리했다.

프로젝트 기간: 2026-08-18 ~ 2026-09-02
글 범위: MySQL 8 GTID·TLS Primary/Replica와 수동 Failover

MeetBack DB는 MySQL 8.0.46 두 대로 구성했다. 평상시에는 Primary 한 곳으로 쓰기를 보내고, 장애가 나면 복제 상태를 확인한 뒤 Replica로 전환할 수 있도록 준비했다.

자동 Failover보다 수동 승격을 선택한 이유

처음에는 Primary가 내려가면 자동으로 Replica를 승격하는 방법을 검토했다. 다만 노드 두 대만으로는 실제 서버 장애와 네트워크 단절을 구분하기 어렵다. 잘못 승격하면 두 서버가 동시에 쓰기를 받는 split-brain이 생길 수 있었다.

자동 전환에는 정족수와 상태 판단, 접속 주소 변경, 기존 Primary 차단과 재편입 절차까지 필요했다. 프로젝트 규모에서 얻을 이점에 비해 운영 복잡도가 커진다고 판단했다.

이 환경의 역할과 전환 원칙은 아래처럼 정했다.

  • App 쓰기는 DB1 Primary에만 전달
  • DB2는 read_only=ON, super_read_only=ON으로 보호
  • 장애 시 복제 상태와 GTID를 확인하고 운영자가 DB2 승격
  • App 접속 주소, 백업 타이머, 모니터링 역할 표시를 함께 전환

자동 HA까지 구성한 것은 아니었다. 운영자가 복제 상태를 확인하고 수동으로 전환하는 구조로 범위를 정했다.

GTID 기반 복제를 구성했다

두 서버에 서로 다른 server_id를 지정하고 아래 설정을 활성화했다.

[mysqld]
server-id = <unique-id>
log_bin = mysql-bin
gtid_mode = ON
enforce_gtid_consistency = ON
log_replica_updates = ON

Replica는 SOURCE_AUTO_POSITION=1로 연결했다. 바이너리 로그 파일명과 위치를 직접 추적하는 대신 GTID로 실행된 트랜잭션을 확인하도록 했다. GTID의 원본 UUID와 순번을 통해 승격이나 재편입 때 어디까지 반영됐는지 비교할 수 있었다.

복제 계정은 Replica의 내부 주소에서만 접속할 수 있게 하고 TLS를 요구했다. 접속 시험에서 암호화 방식이 실제로 협상되는지 확인한 다음 복제 채널을 설정했다.

CHANGE REPLICATION SOURCE TO
    SOURCE_HOST = '<primary-private-address>',
    SOURCE_PORT = 3306,
    SOURCE_USER = '<replication-user>',
    SOURCE_PASSWORD = '<secret>',
    SOURCE_AUTO_POSITION = 1,
    SOURCE_SSL = 1;

START REPLICA;

첫 번째 문제: 일반 로그인은 되는데 Replication Channel은 실패했다

처음 복제 비밀번호는 긴 임의 문자열로 만들었다. MySQL 클라이언트로 Primary에 TLS 로그인은 됐지만 Replica에서 CHANGE REPLICATION SOURCE TO를 실행하자 아래 오류가 나왔다.

ERROR 3056 (HY000):
The password provided for the replication user exceeds the maximum length of 32 characters

이어 실행한 START REPLICA도 실패했다.

ERROR 1200 (HY000):
The server is not configured as replica

일반 로그인에서 사용할 수 있던 비밀번호가 복제 메타데이터에 저장할 수 있는 길이를 넘었다. CHANGE REPLICATION SOURCE TO가 실패해 채널이 만들어지지 않았고, 뒤의 시작 명령도 실행할 대상이 없었다.

복제 전용 비밀번호를 길이 제한 안에서 다시 만들고 Primary 계정과 Replica 채널을 함께 수정했다. 이후에는 로그인 성공 여부와 채널 설정 성공 여부를 따로 확인했다.

복제가 실제로 동작하는지 확인했다

SHOW REPLICA STATUS\G에서 아래 상태를 확인했다.

Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Seconds_Behind_Source: 0
Last_IO_Error:
Last_SQL_Error:
Auto_Position: 1

IO 스레드는 원본에서 이벤트를 가져오고 SQL 스레드는 relay log를 실행한다. SQL 스레드가 Yes여도 현재 원본과 연결돼 있다는 뜻은 아니므로 두 상태를 함께 확인했다.

Primary에 검증용 테이블과 행을 만든 뒤 Replica에서 같은 데이터와 gtid_executed를 확인했다. Replica에 직접 삽입을 시도했을 때는 super_read_only 오류로 거부됐다. 변수 설정뿐 아니라 실제 쓰기 차단도 확인했다.

두 번째 문제: 주소 전환 직후 IO Thread가 Connecting이었다

DB를 전용망으로 옮긴 직후에는 Replica에 아래 상태가 표시됐다.

Replica_IO_Running: Connecting
Replica_SQL_Running: Yes
Seconds_Behind_Source: NULL
Last_IO_Error: Can't connect to MySQL server ... (111)

잠시 뒤 설정 변경 없이 Yes/Yes, 복제 지연 0초로 회복됐다. 원본 MySQL이 수신 포트를 다시 열기 전에 Replica가 먼저 접속을 시도했고, 채널은 정해진 간격에 따라 재접속하고 있었다.

그때 RESET REPLICA ALL을 실행하면 정상 채널 정보까지 지울 수 있었다. 먼저 아래 항목을 확인했다.

  1. Primary MySQL 서비스의 실행 상태
  2. 내부 주소의 3306 수신 포트
  3. Replica에서 Primary까지 TCP 연결
  4. 재시도 간격이 지난 뒤 복제 상태
  5. 계속 실패할 경우 계정 Host, TLS, 경로와 원본 설정

재시작 직후의 Connecting은 재시도 간격을 기다린 뒤 다시 확인했다. 계속 실패하는 경우에만 추가 설정을 조사하도록 순서를 정했다.

DB망 전환 시 관련 설정을 한 번에 바꿨다

DB 주소를 바꾸면서 함께 수정할 설정을 목록으로 정리했다.

  • Replica의 SOURCE_HOST
  • 복제 계정의 Host 조건
  • App·마이그레이션 계정의 Host 조건
  • mysqld_exporter 접속 주소
  • Prometheus 수집 대상과 역할 표시
  • NFS 백업 export 허용 대상
  • 모니터링 서버의 라우팅

기본 설정에는 루프백 주소가 남아 있었지만 나중에 읽는 zz- 설정에서 전용망 주소로 덮어쓰고 있었다. 파일 검색 결과와 함께 실행 중인 수신 주소를 확인했다.

sudo ss -lntp '( sport = :3306 )'
sudo mysql -NBe "SHOW VARIABLES LIKE 'bind_address';"

최종적으로 전용망 주소 하나에서만 MySQL 접속을 받았다.

Failover는 DB 명령만의 문제가 아니었다

수동 장애 전환 절차에는 아래 작업을 함께 넣었다.

1. Primary가 실제로 중지됐는지 확인
2. Replica IO/SQL 상태와 GTID 비교
3. 남은 relay log 적용 확인
4. Replica의 read_only와 super_read_only 해제
5. application DB endpoint 전환
6. backup timer를 새 Primary로 이동
7. Prometheus role label 전환
8. 기존 Primary가 돌아오면 바로 쓰기 허용하지 않고 Replica로 재편입

이 단계에서는 실제 Primary 장애부터 원래 구조로 돌아오는 전체 훈련은 아직 진행하지 못했다. 작성한 절차와 실제로 검증한 범위를 구분해 남겼다.

Primary를 바꾸면 DB 설정만 바뀌는 것이 아니었다. App 접속 주소, 백업 담당 서버, 모니터링 역할도 함께 맞춰야 했다. 이번 구성에서는 복제와 쓰기 차단을 시험하고 이 변경 항목들을 수동 전환 절차에 정리했다.

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 ↑ ↓ 결과 이동