보관함

MySQL / MariaDB 복제(Replication) 정리 – 동작 원리, 설정, 복제 지연 해결

복제(Replication)는 DB 데이터를 두 대 이상에 복제해 두는 방식이다. 가장 기본 구성은 마스터(master) 1대 + 슬레이브(slave) 1대이고, master-master, 다중 slave 로도 쓴다. 비동기 방식이라 마스터의 변경이 슬레이브에 약간의 지연을 두고 반영된다.

왜 쓰나

  • 실시간 백업 — 마스터가 원본, 슬레이브가 백업. 마스터 장애 시 슬레이브로 전환
  • 부하 분산 — 마스터는 쓰기(insert·update·delete), 슬레이브는 읽기(select) 로 나눠 받음

마스터와 슬레이브의 역할

  • 마스터: 데이터 변경(등록·수정·삭제)이 생기면 바이너리 로그(binary log) 에 기록하고 슬레이브에 전달한다. 마스터는 슬레이브가 몇 대인지 등은 모른다.
  • 슬레이브: 마스터에서 받은 바이너리 로그를 자기 DB 에 반영한다.

바이너리 로그와 복제 형식

바이너리 로그(binlog) 는 DB 에서 일어난 모든 변경 내역이 기록되는 파일이다. 기본은 꺼져 있어서 켜 줘야 한다. 복제 형식은 세 가지다.

  • STATEMENT (SBR) — 실행된 SQL 문을 그대로 복사
  • ROW (RBR) — 변경된 행(row)만 복사. 지금 기본값이자 권장
  • MIXED — 둘을 상황에 따라 섞음

동작 과정

  1. 사용자가 insert/update/delete 로 데이터 변경을 요청한다.
  2. 마스터가 바이너리 로그에 변경 사항을 기록하고 스토리지 엔진에 커밋한다.
  3. 슬레이브의 I/O 스레드가 마스터에 이벤트를 요청하면, 마스터의 dump 스레드가 바이너리 로그를 전송한다.
  4. 슬레이브는 받은 내용을 릴레이 로그(relay log)에 기록한다.
  5. 슬레이브의 SQL 스레드가 릴레이 로그를 읽어 스토리지 엔진에 반영한다.

설정 — Master

마스터 설정 파일(/etc/mysql/mariadb.conf.d/50-server.cnf 또는 /etc/my.cnf)에 넣는다.

재시작 후 슬레이브가 접속할 복제 전용 계정을 만든다. (identified by 를 붙이는 옛 문법 대신 CREATE USER 로 나눠 쓰는 것이 지금 방식이다. 접속 IP 대역도 제한한다.)

※ 참고 SHOW MASTER STATUS 의 File 명과 Position 번호를 기록해 둔다. DB 를 재시작하면 이 값이 바뀔 수 있으니, 슬레이브 설정 직전에 확인한다.

설정 — Slave

재시작 후 마스터를 가리키게 설정한다.

Slave_IO_Running 과 Slave_SQL_Running 이 둘 다 Yes 이고 Seconds_Behind_Master 가 0 에 가까우면 정상이다.

확인

마스터에서 DB·테이블·데이터를 만들고 슬레이브에서 그대로 보이는지 확인한다.

주의

  • 마스터와 슬레이브의 MySQL/MariaDB 버전을 같게 맞춘다. 꼭 달라야 하면 슬레이브가 상위 버전이어야 한다.
  • 마스터 → 슬레이브 순서로 가동한다.
  • 바이너리 로그는 계속 쌓이므로 보관 기간을 정한다. (지금은 expire_logs_days 대신 binlog_expire_logs_seconds 를 쓴다. 예: 604800 = 7일)
  • 슬레이브에 직접 쓰기를 하면 데이터가 어긋나 복제가 깨진다. 슬레이브는 read_only(가능하면 super_read_only) 로 둔다.

복제 지연(Replication Lag)

마스터에서는 여러 스레드가 동시에 쓰기를 하는데, 슬레이브에서 이를 반영하는 SQL 스레드는 기본적으로 1개라 처리가 밀린다. 이것이 복제 지연이다. 병렬 복제로 스레드를 늘려도 근본 원인은 남는다.

지연 원인

  • 느린 쿼리(Long Query) — STATEMENT 복제에서 1시간짜리 쿼리를 슬레이브가 그대로 다시 실행하면, 그 1시간 동안 지연된다.
  • 쓰기량 증가 — 쓰기 쿼리 자체가 늘면 복제할 양도 늘어 지연. 사용량 증가 때문이면 계속 벌어질 수 있고, 보통은 낮에 벌어졌다가 새벽에 따라잡는 패턴
  • 락(lock) 이슈 — 슬레이브에서 메타데이터 락 등으로 쿼리가 막힘
  • 하드웨어 — 디스크 I/O 성능, OS 파라미터, 느린 디스크(7200rpm HDD 등)
  • 슬레이브 부하 — 슬레이브의 읽기 트래픽·배치·백업이 겹쳐 처리 성능이 떨어짐
  • 데이터 불일치로 인한 복제 중단 — 지울 행이 없거나 넣을 행이 이미 있으면 슬레이브가 판단 못 하고 복제를 멈춤. 누군가 슬레이브에 직접 쓰기를 한 경우가 많다.

해결

  • 쿼리 성능 개선 — 느린 쿼리면 인덱스 추가·쿼리 수정으로 실행 속도를 높인다.
  • 병렬 복제 — 복제 적용 worker 스레드를 늘린다. 무작정 많다고 좋진 않고, 16개 이상은 효과가 거의 없는 경우가 많다.

※ 참고 위는 MySQL 변수명이다. MySQL 8.0.26+ 는 replica_parallel_workers, replica_parallel_type 로 이름이 바뀌었고, MariaDB 는 slave_parallel_threads 를 쓴다.

  • 복제 형식 조정(SBR/RBR) — 1시간 돌아도 결국 1건만 바꾸는 쿼리라면 세션에서 ROW 로 바꾸는 게 낫다.

  • 데이터 경량화 — 데이터가 많을수록 불리하다. 서비스에 꼭 필요한 데이터만 남기고 로그성 테이블은 다른 DB 로 분리하거나 삭제한다.

복제가 깨졌을 때

데이터 불일치로 멈췄을 때, 원인을 확인한 뒤에만 한 건을 건너뛰거나 위치를 다시 지정한다.

참고한 자료: DANIDANI – MySQL(MariaDB) Replication, rlawls1991 – MySQL Replication

관련 글: MariaDB 운영 메모 – 계정과 권한, 백업과 복원, 복제(Replication), MySQL 튜닝 (from 나프다)

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

  

  

  

이 사이트는 Akismet을 사용하여 스팸을 줄입니다. 댓글 데이터가 어떻게 처리되는지 알아보세요.