Skip to content
난이도 면접 빈출문제은행 3

복제 구조와 GTID 2 ​

복제 구조와 GTID에서 본 것처럼 복제(replication)는 소스(source)의 바이너리 로그(binary log)를 레플리카(replica)가 받아 적용하는 구조다. 이 문서는 복제를 실제로 연결하는 설정과, 레플리카가 "어디까지 받았는지"를 기억하는 두 방식을 다룬다. 파일 위치로 기억하느냐 GTID(Global Transaction Identifier, 전역 트랜잭션 식별자)로 기억하느냐에 따라 장애 조치(failover)의 난이도가 크게 달라진다.

설정의 뼈대 ​

sql
-- 소스: 복제 전용 계정
CREATE USER 'repl'@'%' IDENTIFIED BY '...';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

-- 레플리카: 소스 지정 후 시작 (GTID 기반)
CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = 'source-db', SOURCE_PORT = 3306,
  SOURCE_USER = 'repl', SOURCE_PASSWORD = '...',
  SOURCE_SSL = 1, SOURCE_AUTO_POSITION = 1;
START REPLICA;
SHOW REPLICA STATUS\G

MySQL 8.4는 바이너리 로그가 기본으로 켜져 있다(log_bin). 복제에 참여하는 서버는 각자 서로 다른 server_id를 가져야 한다. 소스가 레플리카를 이 번호로 구별하고, 레플리카도 자기 번호가 찍힌 이벤트(바이너리 로그에 적힌 변경 한 건)를 걸러 내기 때문이다. 서로를 복제하는 구성에서 자기가 만든 변경이 되돌아와도 다시 적용하지 않게 하려는 것이다. 8.4의 기본 인증 플러그인(authentication plugin)인 caching_sha2_password는 비밀번호를 평문으로 보내지 않으려고 암호화된 연결이나 소스의 공개 키를 요구한다. 둘 다 없으면 복제 계정이 접속에 실패하므로, 예시처럼 SOURCE_SSL = 1을 주거나 GET_SOURCE_PUBLIC_KEY = 1로 소스의 공개 키를 받아 오게 한다.

바이너리 로그 위치 기반 복제 ​

바이너리 로그는 binlog.000012 같은 파일 여러 개로 나뉘어 쌓인다. 위치 기반 복제에서는 레플리카가 "소스의 어느 파일, 몇 번째 바이트까지 받았고 적용했는가"라는 좌표로 진행 상황을 기억한다. 처음 연결할 때는 SOURCE_LOG_FILE과 SOURCE_LOG_POS로 시작 좌표를 직접 지정한다.

문제는 이 좌표가 서버마다 다르다는 점이다. 같은 트랜잭션(transaction)이라도 소스에서는 binlog.000012의 4567번 위치에, 레플리카 자신의 바이너리 로그에서는 전혀 다른 파일·위치에 기록된다. 그래서 소스가 죽고 레플리카 B를 새 소스로 올리면, 나머지 레플리카 C는 "B의 바이너리 로그에서 어디부터 받아야 하는지"를 알 수 없다. 운영자가 C가 마지막으로 적용한 트랜잭션을 B의 로그에서 찾아 좌표를 계산해야 하고, 틀리면 트랜잭션이 빠지거나 두 번 적용된다.

GTID 기반 복제 ​

GTID는 커밋(commit)된 트랜잭션마다 붙는, 전체 복제 구성에서 유일한 번호다. 형식은 source_id:transaction_id다. 앞부분은 트랜잭션이 처음 실행된 서버의 UUID(Universally Unique Identifier, 범용 고유 식별자)이고, 뒷부분은 그 서버에서 커밋 순서대로 1부터 매기는 번호다.

text
3E11FA47-71CA-11E1-9E33-C80AA9429562:23        -- 그 서버의 23번째 트랜잭션
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5:11    -- GTID 집합: 1~5번과 11번

서버는 자기가 실행한 GTID 전체를 gtid_executed라는 GTID 집합으로 기억한다. 이 번호는 어느 서버의 로그에 기록되든 바뀌지 않으므로, "좌표"가 아니라 "무엇을 이미 했는가"로 진행 상황을 비교할 수 있다. MySQL 8.4에서는 서버UUID:태그:번호 형태의 태그 GTID(tagged GTID)도 새로 쓸 수 있어, 특정 작업 묶음에 이름을 붙이면 나중에 GTID 집합만 보고도 어떤 트랜잭션이 그 작업에서 나왔는지 가려낼 수 있다.

GTID가 주는 이점은 두 가지다.

  • 자동 위치 지정(auto-positioning): SOURCE_AUTO_POSITION = 1이면 레플리카가 접속할 때 자기가 가진 GTID 집합을 소스에 보낸다. 소스는 그 집합에 없는 트랜잭션만 골라 보낸다. 운영자가 좌표를 계산할 필요가 없다.
  • 자동 건너뛰기: 이미 커밋한 GTID가 다시 오면 서버는 오류 없이 건너뛴다. 그래서 같은 트랜잭션이 한 서버에 두 번 적용되지 않는다.

켜려면 gtid_mode=ON과 enforce_gtid_consistency=ON을 함께 설정한다. 8.4에서도 둘 다 기본값은 OFF다. enforce_gtid_consistency는 GTID 하나로 안전하게 기록할 수 없는 문장을 거부한다. 대표 예는 한 트랜잭션에서 InnoDB 테이블과 MyISAM 같은 비트랜잭션 테이블을 함께 고치는 경우다. 비트랜잭션 테이블의 변경은 롤백(rollback)되지 않아, GTID 하나로 묶은 트랜잭션이 통째로 적용되거나 통째로 취소된다는 전제를 지킬 수 없기 때문이다.

장애 조치에서의 차이 ​

비교위치 기반GTID 기반
진행 상황소스의 파일명 + 위치실행한 GTID 집합
새 소스로 갈아탈 때새 소스의 좌표를 사람이 계산접속만 바꾸면 빠진 것만 받음
중복 적용좌표를 틀리면 발생같은 GTID는 자동으로 건너뜀
확인Exec_Source_Log_PosExecuted_Gtid_Set

Exec_Source_Log_Pos와 Executed_Gtid_Set은 둘 다 SHOW REPLICA STATUS 결과 항목으로, 어느 소스 로그 위치까지 적용했는지와 적용한 GTID 집합을 보여 준다.

GTID를 쓰면 여러 레플리카 중 가장 많이 받은 서버를 고르기도 쉽다. 각 서버의 gtid_executed를 비교해 다른 서버의 트랜잭션을 모두 포함한(가장 많이 적용한) 서버를 새 소스로 올리고, 나머지는 CHANGE REPLICATION SOURCE TO로 소스 주소만 바꾸면 된다. 이런 절차를 자동으로 해 주는 것이 그룹 복제와 InnoDB 클러스터다.

면접 포인트 ​

  • "복제를 연결하려면 무엇이 필요한가요?" → 서버마다 다른 server_id, REPLICATION SLAVE를 준 복제 계정, 8.4 기본 인증이면 SOURCE_SSL = 1이나 GET_SOURCE_PUBLIC_KEY = 1.
  • "위치 기반 복제의 장애 조치가 왜 번거롭나요?" → 같은 트랜잭션의 파일·위치 좌표가 서버마다 달라 새 소스의 좌표를 사람이 계산해야 한다.
  • "GTID를 쓰면 무엇이 좋아지나요?" → 서버마다 다른 파일 좌표 대신 유일한 트랜잭션 번호로 비교, 자동 위치 지정과 중복 건너뛰기로 장애 조치가 단순해진다.

관련 문서