DataBase/MySQL

MySQL 복제(레플리카) 설정하기

왈왈디 2025. 7. 20. 20:42
728x90

복제란?

복제는 한 서버에서 다른 서버로 데이터가 동기화되는 것을 말한다.

  • 소스(Source) 서버: 원본 데이터를 가진 서버
  • 레플리카(Replica) 서버: 복제된 데이터를 가지는 서버

소스 서버에서 데이터 및 스키마에 대한 변경이 최초로 발생한다. 

레플리카 서버에서는 이러한 변경 내역을 소스 서버로부터 전달 받아
자신이 가지고 있는 데이터에 반영함으로써 소스 서버에 저장된 데이터와 동기화 시킨다.

 

복제의 목적은 주로 다음 4가지이다.

  1. 스케일 아웃(Scale-out)
  2. 데이터 백업
  3. 레플리카 서버를 데이터 분석용 서버로 사용
  4. 데이터의 지리적 분산

복제 아키텍처

복제 아키텍처를 이해하기 위해서두 가지 로그를 알아두어야 한다.

  • 바이너리 로그(Binary Log): MySQL 서버에서 발생하는 모든 변경 사항을 순서대로 기록한다.
    데이터의 변경 내역 뿐만 아니라, 데이터베이스나 테이블의 구조 변경과 계정이나 권한의 변경 정보까지 모두 저장된다.
    복제는 이 바이너리 로그를 기반으로 구현됐다. 소스 서버에서 생서된 바이너리 로그가 레플리카 서버로 전송되고 레플리카 서버에서는 해당 내용을 로컬 디스크에 저장한 뒤 자신이 가진 데이터에 반영함으로써 동기화가 이루어진다.
  • 릴레이 로그(Relay Log): 레플리카 서버에서 소스 서버의 바이너리 로그를 읽어 로컬 디스크에 저장해둔 파일이다.

MySQL 복제는 세 개의 스레드에 의해 작동한다.

  • 바이너리 로그 덤프 스레드(Binary Log Dump Thread): 레플리카 서버가 소스 서버에 접속해 바이너리 로그 정보를 요청한다.
    소스 서버에서 바이너리 로그 덤프 스레드를 생성해서 바이너리 로그의 내용을 레플리카 서버로 전송한다.
    각 이벤트를 읽을 때 일시적으로 바이너리 로그에 잠금을 수행하며, 이벤트를 읽고난 후에는 바로 잠금을 해제한다.
  • 레플리케이션 I/O 스레드(Replication I/O Thread): 레플리카 서버에서 소스 서버의 바이너리 로그 이벤트를 가져와 로컬 서버의 파일(릴레이 로그)로 저장하는 역할이다.
    복제가 시작되면 레플리카 서버는 I/O 스레드를 생성하고, 복제가 멈추면 종료된다.
  • 레플리케이션 SQL 스레드(Replication SQL Thread): 레플리카 서버에서 작성된 릴레이 로그 파일의 이벤트들을 읽고 실행한다. 

복제가 시작되면 레플리카 서버는 총 세 가지 유형의 복제 관련 데이터를 생성하고 관리한다.

  • 릴레이 로그(Relay Log): 레플리케이션 I/O 스레드에 의해 작성되는 파일로, 소스 서버의 바이너리 로그에서 읽어온 이벤트(트랜잭션) 정보가 저장된다. 
  • 커넥션 메타데이터(Connection Metadata): 레플리케이션 I/O 스레드에서 소스 서버에 연결할 때 사용하는 DB 계정 정보 및 현재 읽고 있는 소스 서버의 바이너리 파일명과 파일 내 위치 값등이 담겨 있다.
    mysql.slave_master_info 테이블에 저장된다.
  • 어플라이어 메타데이터(Applier Metadata): 레플리케이션 SQL 스레드에서 릴레이 로그에 저장된 소스 서버의 이벤트들을 레플리카 서버에 적용(Relay)하는 컴포넌트를 어플라이어(Applier)라고 한다. 
    최근 적용된 이벤트에 대해 해당 이벤트가 저장돼 있는 릴레이 로그 파일명과 파일 내 위치 정보 등을 담고 있고, 이 정보들을 바탕으로 레플리카 서버에 나머지 이벤트들을 적용한다.
    mysql.slave_relay_log_info 테이블에 저장된다.

복제 타입

복제는 소스 서버의 바이너리 로그에 기록된 변경 내역들을 식별하는 방식에 따라 두가지로 나뉜다.

  • 바이너리 로그 파일 위치 기반 복제
  • 글로벌 트랜잭션 ID 기반 복제

이번엔 바이너리 로그 파일 위치 기반 복제에 대해서만 살펴보자.

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

복제 기능이 처음 도입됐을 때부터 제공된 방식으로,
레플리카 서버에서 소스 서버의 바이너리 로그 파일명과 파일 내에서의 위치(Offset 또는 Position)로
개별 바이너리 로그 이벤트를 식별해서 복제가 진행되는 형태이다.

 

복제를 처음 구축할 때 레플리카 서버에 소스 서버의 어떤 이벤트부터 동기화를 수행할 것인가에 대한 정보를 설정해야 한다.

레플리카 서버는 소스 서버의 어느 이벤트까지 로컬 디스크로 가져왔고 또 적용했는지에 대한 정보를 관리하며
소스 서버에 해당 정보를 전달해 그 이후의 바이너리 로그 이벤트들을 가져온다.

 

따라서 소스 서버에서 발생한 각 이벤트에 대한 식별이 반드시 필요하고,
바이너리 로그 파일 위치 기반 복제 방식에서는 파일명과 파일 내에서의 위치 값(File Offset)의 조합으로 식별한다.

 

또 중요한 점은 복제에 참여한 MySQL 서버들이 모두 고유한 server_id 값을 가지고 있어야 한다.

server_id는 시스템 변수 중 하나로, 사용자가 설정할 수 있으며 기본값은 1이다.

 

복제 구축

바이너리 로그 파일 위치 기반의 복제 구축 방식에 대해 알아보자.

1. 설정 준비

복제를 사용하려면 소스 서버에서 반드시 바이너리 로그가 활성화돼 있어야 하며,

복제 구성원이 되는 각 MySQL 서버가 고유한 server_id를 가져야 한다.

MySQL 8.0에서는 바이너리 로그가 기본적으로 활성화돼 있다.

 

바이너리 로그 파일 위치나 파일명을 따로 설정하고 싶다면 log_bin 시스템 변수를 통해 원하는 값으로 설정할 수 있다.

동기화 방식이나, 캐시를 위한 메모리 크기, 파일 크기, 보관 주기 등도 지정할 수 있다.

 

아래 명령으로 소스 서버에서 바이너리 로그가 정상적으로 기록되고 있는지 확인할 수 있다.

SHOW MASTER STATUS;

 

레플리카 서버가 소스 서버로 승격될 수 있음을 고려하면 log_slave_updates 시스템 변수를 명시하는 것이 좋다.

기본적으로 레플리카 서버는 복제에 의한 데이터 변경 사항은 자신의 바이너리 로그에 기록하지 않는데,

log_slave_updates 시스템 변수를 설정하면 복제에 의한 데이터 변경 내용도 자신의 바이너리 로그에 기록하게 된다.

 

2. 복제용 계정 준비

레플리카 서버가 사용할 복제용 계정이 필요하다.

복제에 사용되는 권한만 주어진 별도의 계정을 생성해 사용하는 것이 좋다.

이 계정은 반드시 REPLICATION SLAVE 권한을 가지고 있어야 한다.

 

3. 데이터 복사

복제를 시작하기 전에 소스 서버의 데이터를 레플리카 서버로 가져와서 적재해 두어야 한다.

MySQL 엔터프라이즈 백업이나 mysqldump 같은 툴을 이용해서 데이터를 복사하면 된다.

 

4. 복제 시작

데이터 복사까지 완료되면 복제를 시작하면 된다.

mysqldump를 이용해 소스 서버의 데이터를 백업 받아 11:20 쯤에 레플리카 서버에 모두 적재된 경우,

복제를 시작하는 시점이 11:45이라면
레플리카 서버 데이터가 11:20 부터 11:45까지의 데이터에 대해 소스 서버보다 지연된 상태라고 할 수 있다.

 

복제를 설정하여 복제를 시작하자.

CHANGE REPLICATION SOURCE TO (또는 CHANGE MASTER TO) 명령으로 mysqldump로 백업 받은 파일의 헤더 부분에서 

해당 명령어를 참조할 수 있다.

 

대략 24번째 줄에 있는 "CHANGE MASTER"로 시작하는 줄만 텍스트 편집기에 복사해둔다.

linux> less /tmp/source_data.sql
...

-- Position to start replication or point-in-time recovery from
--

-- CHANGE MATSER TO MASTER_LOG_FILE='binary-log.000002', MASTER_LOG_POS=2708;

 

 

이제 편집기에 복사해 둔 내용에

  • 소스 서버 MySQL 서버의 호스트명
  • 포트
  • 복제용 사용자 계정
  • 비밀 번호

등을 다음과 같이 추가해 복제 설정 명령을 준비한다.

-- // MySQL 8.0.23 이상 버전
CHANGE REPLICATION SOURCE TO
	SOURCE_HOST='source_server_host',
    SOURCE_PORT=3306,
    SOURCE_USER='repl_user',
    SOURCE_PASSWORD='repl_user_password',
    SOURCE_LOG_FILE='binary-log.000002',
    SOURCE_LOG_POS=2708,
    GET_SOURCE_PUBLIC_KEY=1;
    
-- // MySQL 8.0.23 미만 버전
CHANGE MASTER TO
	MASTER_HOST='source_server_host',
    MASTER_POST=3306,
    MASTER_USER='repl_user',
    MASTER_PASSWORD='repl_user_password',
    MASTER_LOG_FILE='binary-log.0000002',
    MATSER_LOG_POS=2708,
    GET_MASTER_PUBLIC_KEY=1;

 

 

SOURCE_HOST는 소스 서버를 의미하고 소스 서버의 IP 혹은 도메인 정보를 넣으면 도니다.

GET_SOURCE_PUBLIC_KEY는 RSA 키 기반 비밀번호 교환 방식의 통신을 위해 공개키(Public Key)를 소스 서버에 요청할 것인지 여부를 나타낸다. 에러가 발생할 수 있으므로 반드시 설정해야 한다.

 

이 명령을 그대로 레플리카 서버의 MySQL에 로그인해서 실행한 뒤 아래 명령을 실행해보면

복제 관련 정보가 레플리카 서버 MySQL에 등록돼 있는 것을 확인할 수 있다.

SHOW REPLICA STATUS;
-- 또는 SHOW SLAVE STATUS

 

하지만 Replica_IO_Running, Replica_SQL_Running 컬럼값이 "No" 로 되어있는데

아직 복제 관련 정보 등록만 된 것이지 동기화가 시작되지 않았음을 의미한다.

 

이 상태에서 아래 명령을 실행하면 두 값이 "Yes"로 바뀌면서
동기화가 지연된 기간의 변경 사항들을 소스 서버로부터 가져와 적용하게 된다.

START REPLICA;
-- 또는 START SLAVE

 

복제 중 소스 서버로부터 넘어온 트랜잭션이 제대로 실행되지 못하고
에러가 발생해 복제가 멈추는 현상이 발생하기도 한다.

 

대부분은 사용자의 실수로 인한 경우가 많고, 대표적인 에러가 중복 키 에러다.

바이너리 로그 위치 기반 복제에서는 sql_slave_skip_counter 시스템 변수를 이용해 문제되는 트랜잭션을 건너뛸 수 있다.

 

아래와 같이 복제를 중단한 후 sql_slave_skip_counter 변수의 값을 1로 지정해 레플리케이션 SQL 스레드를 재시작하면

레플리카 서버는 에러가 발생한 INSERT 쿼리를 건너뛰고 정상적으로 복제를 재개하게 된다.

STOP SLAVE SQL THREAD;
SET GLOBAL sql_slave_skip_counter=1;
START SLAVE SQL_THREAD;

 

참고 자료

  • Real MySLQ 8.0 2권 - 16. 복제

 

728x90