Files
chocomae/doc/plan/db/08-synology-replication-setup.md
T
2026-09-15 10:38:05 +09:00

21 KiB

Synology 읽기 복제본 구축 가이드

실시간 MariaDB Replication으로 Synology NAS를 운영 DB의 최신 사본으로 유지

  • 작성일: 2026-09-15
  • 대상 환경: AWS EC2 (운영 MariaDB 10.11.13) ↔ Synology NAS (MariaDB 10)
  • 이 문서는 계획 문서입니다. 실제 구현은 아직 하지 않았습니다.

1. 개념: MariaDB Replication

마스터-슬레이브 구조

┌─────────────────────────────┐
│  AWS EC2 (마스터)            │
│  MariaDB 10.11.13           │
│  - 모든 쓰기 실행            │
│  - Binlog 기록               │
│  :3306                      │
└──────────────┬──────────────┘
               │ 바이너리 로그 복제
               │ (지속적, 초단위)
               ▼
┌─────────────────────────────┐
│  Synology NAS (슬레이브)     │
│  MariaDB 10                 │
│  - 로그 수신 & 적용          │
│  - 읽기만 가능               │
│  mariadb.jisangs.com:3306   │
└─────────────────────────────┘

동작 원리:

  1. 마스터에서 모든 변경(INSERT/UPDATE/DELETE)을 바이너리 로그에 기록
  2. 슬레이브가 지속적으로 마스터의 로그를 읽음
  3. 슬레이브가 같은 명령을 로컬에서 재실행 (replay)
  4. 결과적으로 마스터와 슬레이브의 데이터가 항상 동일 (보통 < 1초 지연)

현재 시스템과의 비교:

항목 현재 (매일 덤프) 변경 후 (실시간 복제)
네트워크 NAS가 마스터 SELECT 마스터가 NAS에 쓰기 푸시
용량 SQL 파일 (매일 수백 MB) 바이너리 로그 (변경분만)
복원 속도 수십 분 초 단위
운영 DB 부하 매일 높음 (SELECT * 시간) 거의 없음
백업 용도 덤프 파일 자체 복제본 + 덤프 (필요시)
분석 쿼리 영향 운영 DB 느려짐 복제본이므로 무관

2. 단계별 구현

단계 1: 운영 DB 설정 (AWS EC2)

2-1. Binlog 활성화

mariadb-dumpmariadb-restore를 쓰는 현재 시스템과 달리, 복제를 위해서는 바이너리 로그가 계속 켜져 있어야 합니다.

Docker 컨테이너에서 확인:

# EC2 인스턴스에서
docker exec <container_name> mariadb -e "SHOW VARIABLES LIKE 'log_bin%';"
# 결과 예: log_bin = ON

만약 OFF라면:

# Docker 실행 시 또는 my.cnf에 추가
[mysqld]
log_bin = mysql-bin
binlog_format = ROW
binlog_expire_logs_days = 14  # 14일 후 자동 삭제
server_id = 1                  # 마스터는 1, 슬레이브는 2+

Docker 컨테이너 재시작 필요 (또는 운영 설정 파일 재로드)

온라인 확인 및 임시 활성화 (재시작 없음):

-- 연결: mysql -h chocomae.jinaju.com -u root -p
SET GLOBAL binlog_format = 'ROW';
SET GLOBAL log_bin = ON;

-- 확인
SHOW VARIABLES LIKE 'binlog%';
SHOW MASTER STATUS;  -- File='mysql-bin.000001', Position=XXX 나와야 함

중요: 컨테이너를 재시작하면 SET GLOBAL은 초기화됩니다. 영구 적용은 Docker 설정 파일에서 해야 합니다.

2-2. 복제 계정 생성

Synology(슬레이브)에서 마스터의 로그를 읽기 위한 전용 계정:

-- 운영 DB에서 (EC2, root 권한)
CREATE USER 'replication'@'mariadb.jisangs.com' IDENTIFIED BY '복제_비밀번호_여기_입력';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'replication'@'mariadb.jisangs.com';
FLUSH PRIVILEGES;

-- 확인
SHOW GRANTS FOR 'replication'@'mariadb.jisangs.com';

보안: 비밀번호는 강력하게. Synology의 접속 파일(.chocomae_replication.cnf 같은)에 저장하되, 권한을 600 (읽기 전용)으로 제한합니다.

2-3. 현재 로그 위치 기록

초기 데이터 복사(2-5단계)를 시작하기 전에 현재의 마스터 로그 상태를 기록해야 합니다. 그 이후의 변경분부터 복제하므로:

SHOW MASTER STATUS;

출력 예:

File             Position  Binlog_Do_DB  Binlog_Ignore_DB
mysql-bin.000001 154

이 값(mysql-bin.000001, 154)을 메모해 두세요. 슬레이브 설정(2-7단계)에서 사용합니다.


단계 2: Synology 초기화

2-4. 현재 스테이징 DB 확인

Synology의 MariaDB 상태 확인:

# Synology SSH에서
mariadb -u root -p -e "SELECT @@version, @@datadir;"

현재 mariadb.jisangs.com:3306에 기존 chocomae DB가 있습니다 (스테이징/테스트용).

2-5. 초기 데이터 복사 (Binlog 이전까지)

방법 A: 현재 backup-db.sh 스크립트 활용 (추천)

이미 작성된 backup-db.shmariadb-dump --single-transaction을 사용합니다. 이것이 바로 복제용 초기 데이터 복사의 좋은 도구입니다.

  1. 운영 DB에서 현재 상태의 덤프를 받습니다 (위에서 메모한 로그 위치 이후의 변경분만 복제되므로 OK).
  2. Synology에서 그 덤프를 복원합니다.

구체적 커맨드:

# Synology SSH에서
# 1) 기존 테스트 DB를 백업 (선택, 필요하면)
mariadb-dump -u root -p chocomae > /volume1/backup/chocomae_before_replication.sql

# 2) 운영 DB에서 현재 상태의 덤프를 받기 (스테이징의 backup-db.sh 스크립트 참고)
# 또는 EC2에서 Synology로 직접 파이프
mariadb-dump -h chocomae.jinaju.com -u backup -p \
  --single-transaction \
  --default-character-set=utf8mb4 \
  chocomae | mariadb -u root -p chocomae

# (또는) 파일로 저장했다면
mariadb -u root -p chocomae < /volume1/backup/chocomae_latest.sql

이제 Synology의 chocomae DB가 운영 DB와 동일한 상태입니다 (위에서 기록한 로그 위치 시점의).

2-6. Synology MariaDB 설정

슬레이브를 위한 추가 설정. Synology의 MariaDB 설정 파일 (보통 /etc/my.cnf 또는 /var/packages/MariaDB10/target/etc/my.cnf):

[mysqld]
server_id = 2                 # 슬레이브는 2 이상 (마스터와 다른 ID)
skip_slave_start = OFF        # 시작 시 자동으로 복제 시작 (선택)
# 보통은 ON으로 두고 수동 START SLAVE 권장
relay_log = mysql-relay-bin
relay_log_index = mysql-relay-bin.index
log_slave_updates = ON        # 슬레이브도 로그 기록 (선택, 슬레이브의 슬레이브 필요시)
read_only = ON                # 슬레이브에서의 쓰기 금지 (권장)

Synology의 MariaDB 재시작 또는 SSH에서 SET GLOBAL로 설정:

SET GLOBAL server_id = 2;
SET GLOBAL read_only = ON;  # 슬레이브를 읽기 전용으로 (권장)

단계 3: 복제 시작 (Synology)

2-7. CHANGE MASTER TO

2-3단계에서 메모한 운영 DB의 로그 위치를 사용:

-- Synology의 MariaDB에서 (root 또는 관리자)
-- 먼저 기존 복제 설정 확인
SHOW SLAVE STATUS;
-- 아무 것도 없으면 OK, 뭔가 있으면 아래 항목 먼저 실행:
-- STOP SLAVE;
-- RESET SLAVE;

-- 복제 설정
CHANGE MASTER TO
  MASTER_HOST = 'chocomae.jinaju.com',
  MASTER_PORT = 3306,
  MASTER_USER = 'replication',
  MASTER_PASSWORD = '복제_비밀번호',
  MASTER_LOG_FILE = 'mysql-bin.000001',      -- 2-3단계의 File 값
  MASTER_LOG_POS = 154;                      -- 2-3단계의 Position 값

타임존 고려: MariaDB는 일반적으로 UTC 기반이므로 MASTER_CONNECT_RETRY 같은 추가 설정은 대개 불필요합니다. 네트워크 재연결 시간은 기본값(60초)이 적절합니다.

2-8. 복제 시작

START SLAVE;

-- 몇 초 기다린 뒤 상태 확인
SHOW SLAVE STATUS\G

-- 확인할 항목:
-- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes
-- Seconds_Behind_Master: 0 (또는 작은 숫자)
-- Last_Error: (비어 있음)

복제가 정상 동작하면:

  • Slave_IO_Running: Yes — 마스터의 바이너리 로그를 계속 읽는 중
  • Slave_SQL_Running: Yes — 읽은 로그를 Synology에서 재실행 중
  • Seconds_Behind_Master: 0 — 지연 없음 (또는 1~2초 이내)

문제가 있으면:

  • Slave_IO_Running: Connecting — 네트워크 문제. 방화벽, 호스트명, 포트 확인
  • Slave_SQL_Running: No — 로컬 SQL 오류. Last_Error 확인
  • Last_Error에 오류 내용: 보통 "테이블 없음", "컬럼 이름 다름" 등. 4장에서 다룹니다.

3. 권한 관리 및 모니터링

3-1. 사용자 계정 분리

Synology에서 생성할 계정들:

-- 1) 분석용 계정 (읽기 전용)
CREATE USER 'analytics'@'localhost' IDENTIFIED BY 'analytics_password';
GRANT SELECT ON chocomae.* TO 'analytics'@'localhost';
FLUSH PRIVILEGES;

-- 2) 스테이징/개발용 (기존)
-- 이미 있음: backup@... 등

-- 3) 모니터링용 (선택)
CREATE USER 'monitor'@'localhost' IDENTIFIED BY 'monitor_password';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'monitor'@'localhost';

운영 DB (마스터)의 권한은 유지:

  • backup@chocomae.jinaju.com — 백업용 (이미 있음)
  • replication@mariadb.jisangs.com — 복제용 (2-2단계에서 생성)

3-2. 모니터링 쿼리

Synology SSH에서 주기적 확인:

# 매 시간 또는 매 15분마다 실행 (cron 추천)
mariadb -u monitor -p chocomae -e "SHOW SLAVE STATUS\G" > /volume1/logs/replication.log

# 또는 한 줄로
mariadb -u monitor -p -e "SHOW SLAVE STATUS\G" | grep -E 'Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_Error'

확인할 항목:

항목 정상 주의 위험
Slave_IO_Running Yes Connecting No
Slave_SQL_Running Yes (거의 없음) No
Seconds_Behind_Master 0~1 1~10 10+
Last_Error (비어 있음) (있음) (있음)

4. 기존 백업(backup-db.sh)과의 통합

4-1. 현재 백업 스크립트의 역할 변경

현재 backup-db.sh:

  • 실행 위치: Synology
  • 대상: 운영 DB(chocomae.jinaju.com)
  • 방식: mariadb-dump로 전체 SQL 파일 생성
  • 보관: 28일

복제 후 권장 변경:

옵션 A: 그대로 유지 (가장 안전)

  • 기존 스크립트 유지 (매일 운영 DB에서 전체 덤프)
  • 추가로: Synology의 복제본도 매주 백업 (별도 스크립트)
  • 장점: 두 백업이 서로 다른 경로 제공
  • 단점: 운영 DB 부하 계속 (매일)

옵션 B: Synology 백업 중심으로 전환 (권장)

  • 기존 스크립트: 실행 대상을 chocomae.jinaju.comlocalhost로 변경
    DB_HOST="localhost"  # Synology 로컬
    
  • 실행 시간: 기존과 동일 (매일 새벽)
  • 장점: 운영 DB 부하 제거 (복제본에서만 덤프)
  • 단점: 복제 지연 중에 스냅샷이 약간 뒤떨어질 수 있음

옵션 C: 하이브리드 (균형)

  • 주중 (월~금): 복제본에서 백업 (스크립트 변경)
  • 주말 (토): 운영 DB에서 백업 (원본 보장)
  • 월: 복제본 검증 후 운영 DB 백업

4-2. 백업 스크립트 변경 (옵션 B 선택 시)

# backup-db.sh 수정 항목
# 라인 46: DB_HOST="chocomae.jinaju.com" → DB_HOST="localhost"
# 라인 48: DB_PORT="3306" → DB_PORT="3306" (그대로)
# 라인 50: DB_USER="backup" → DB_USER="root" (Synology 로컬이므로)
# 또는 별도 계정 생성

# 그 외는 모두 동일

변경 후 테스트:

# Synology에서
/path/to/backup-db.sh

# 로그 확인
tail -f /path/to/backup_dir/backup.log

5. 장애 시나리오 및 대응

5-1. 복제 지연 (Seconds_Behind_Master > 10)

원인: 운영 DB의 쓰기 폭주, 네트워크 지연, Synology의 처리 능력 한계

대응:

  1. 운영 DB에서 슬로우 쿼리 로그 확인 (long_query_time = 1)
  2. Synology의 CPU/메모리 사용량 확인 (docker stats 또는 top)
  3. 복제 쿼리 재개 전까지 기다림 (보통 자동 복구)
  4. 계속되면 네트워크 대역폭 확인

일시적 해결: 아무 것도 안 하고 기다리기 (복제는 자동으로 따라잡음)

5-2. 복제 중단 (Slave_SQL_Running: No)

원인: 로컬 SQL 오류, 테이블/컬럼 불일치, 제약 조건 위반

대응:

  1. Last_Error 확인 (실제 오류 메시지)
  2. 오류의 SQL을 수동으로 Synology에서 실행해보기
  3. 원인 제거 (보통 운영 DB의 스키마가 바뀐 경우)
  4. STOP SLAVE; START SLAVE; (재시작)
  5. 계속 실패하면 5-4

5-3. 연결 끊김 (Slave_IO_Running: No/Connecting)

원인: 네트워크 이슈, 방화벽, 호스트명 오류, 복제 계정 삭제

대응:

  1. Synology에서 운영 DB로 연결 테스트:
    mariadb -h chocomae.jinaju.com -u replication -p -e "SELECT 1;"
    
  2. 연결되면: STOP SLAVE; START SLAVE; (재시작)
  3. 연결 안 되면:
    • 호스트명 재확인 (ping chocomae.jinaju.com)
    • 방화벽 (AWS 보안 그룹) 확인
    • 복제 계정 확인 (운영 DB에서 SELECT USER FROM mysql.user WHERE User='replication';)

5-4. 복제 재초기화 (완전 초기화 필요한 경우)

복제가 완전히 깨졌거나 마스터와 슬레이브가 불일치한 경우:

-- Synology에서
STOP SLAVE;
RESET SLAVE ALL;

-- 다시 초기화 (2-5단계 ~ 2-8단계 반복)
-- 1. 운영 DB에서 덤프 받기
-- 2. Synology에 복원
-- 3. CHANGE MASTER TO ... START SLAVE;

6. 성능 영향 및 고려사항

6-1. 운영 DB (마스터) 오버헤드

요소 영향도 설명
Binlog 기록 12% 모든 쓰기를 로그에 기록하는 비용
Binlog 파일 크기 ~2GB/월 (예상) 현재 record 저장이 월 ~17만 행 × 파일 크기
복제 스레드 12% 슬레이브가 로그를 읽는 데 필요한 스레드
총 오버헤드 <5% 거의 무시할 수 있는 수준

6-1-1. 현재 시스템과의 실제 비교

현재 (일일 덤프 백업):

매일 밤 Synology에서 운영 DB로 전체 SELECT 쿼리 실행
- 타입: 운영 DB에 대한 대량 SELECT
- 빈도: 1회/일
- 부하: 시간 단위로 높음 (덤프 시간 동안)
- 영향: 이 시간에 실시간 사용자가 영향받을 수 있음

부하 패턴:
▓▓▓▓▓▓▓▓▓▓ (매일 새벽, 고부하)
▁▁▁▁▁▁▁▁▁▁ (나머지 시간, 낮음)

복제 후 (실시간 바이너리 로그 동기화):

운영 DB는 변경분만 로그에 기록 (항상 실행 중)
- 타입: 로그 기록 (매우 가볍고 배치 처리)
- 빈도: 상시
- 부하: 초당 6~10 건 정도 (매우 미미)
- 영향: 무시할 수 있는 수준

부하 패턴:
▁▁▁▁▁▁▁▁▁▁ (상시, 거의 무감지)

결과: 실제로는 부하가 감소합니다 — 매일 덤프 시 높던 SELECT 부하가 제거됩니다.

6-1-2. 위험 시나리오 및 대응

시나리오 1: 기록 저장 폭증

원인: 이벤트, 버그, 또는 대량 데이터 로드

  • 현재: 평균 초당 ~6건 (월 17만 건 / 2.6M초)
  • 위험: 초당 천 건 이상 저장되는 경우

대응:

# Synology에서 모니터링
mariadb -u monitor -p -e "SHOW SLAVE STATUS\G" | grep Seconds_Behind_Master

# 만약 Seconds_Behind_Master > 10이면:
# - 운영 DB의 슬로우 쿼리 로그 확인
# - Synology의 CPU/메모리 사용률 확인
# - 보통 자동으로 따라잡음 (기다리면 OK)

시나리오 2: Synology 디스크 느림

원인: NAS가 RAID 5/6, 다른 작업 경합

  • 현상: 복제 지연 증가 (Seconds_Behind_Master > 30)
  • 지속성: 자동 복구 (바이너리 로그는 계속 축적)

대응:

# 모니터링만 (수동 개입 필요 없음)
# 지연은 자동으로 따라잡음
# 필요시 Synology의 다른 작업 중단

시나리오 3: 네트워크 단절

원인: EC2 ↔ Synology 연결 끊김

  • 현상: Slave_IO_Running: No 또는 Connecting
  • 기간: 자동 재연결 시도 (기본 60초 주기)

대응:

# 1. 연결 테스트
mariadb -h chocomae.jinaju.com -u replication -p -e "SELECT 1;" 2>&1

# 2. 연결 불가면 확인
ping chocomae.jinaju.com           # DNS/네트워크
aws ec2 describe-security-groups   # AWS 보안 그룹 확인

# 3. 수동 재연결
mariadb -u root -p -e "STOP SLAVE; START SLAVE;"

6-1-3. 권장 모니터링 절차

정기 확인 (cron, 매시간):

#!/bin/bash
# Synology에서 /volume1/scripts/check_replication.sh

RESULT=$(mariadb -u monitor -p"비밀번호" -e "SHOW SLAVE STATUS\G" 2>/dev/null)

IO_RUNNING=$(echo "$RESULT" | grep "Slave_IO_Running:" | awk '{print $NF}')
SQL_RUNNING=$(echo "$RESULT" | grep "Slave_SQL_Running:" | awk '{print $NF}')
SECONDS_BEHIND=$(echo "$RESULT" | grep "Seconds_Behind_Master:" | awk '{print $NF}')
LAST_ERROR=$(echo "$RESULT" | grep "Last_Error:" | awk '{print $NF}')

echo "[$(date)] IO=$IO_RUNNING SQL=$SQL_RUNNING Behind=${SECONDS_BEHIND}s Error=$LAST_ERROR" >> /volume1/logs/replication.log

# 이상 발생 시 경고 (선택)
if [ "$IO_RUNNING" != "Yes" ] || [ "$SQL_RUNNING" != "Yes" ]; then
  echo "WARNING: Replication issue detected at $(date)" | mail -s "Synology Replication Alert" admin@example.com
fi

cron 설정:

# Synology SSH에서
crontab -e

# 추가
0 * * * * /volume1/scripts/check_replication.sh
# (매 시간 0분에 실행)

정상 상태 (매시간 확인):

IO=Yes SQL=Yes Behind=0s Error=None
IO=Yes SQL=Yes Behind=1s Error=None

이상 상태 (조사 필요):

IO=Connecting SQL=Yes Behind=X Error=None     # 네트워크 재연결 시도 중
IO=No SQL=No Behind=NULL Error=...            # 심각한 오류, 복제 중단
IO=Yes SQL=No Behind=X Error=...              # SQL 오류, 로그 재생 실패

6-2. Synology의 수신 능력

복제본이 지속적으로 마스터의 로그를 읽어 재실행하므로, Synology의 네트워크 대역폭과 디스크 I/O가 관련됩니다.

  • 네트워크: 로컬 LAN이라면 문제 없음
  • 디스크 I/O: 복제 적용 속도에 영향. NAS의 RAID 설정에 따라 다름

6-3. 백업 용량 및 보관

바이너리 로그 크기 (예상):

  • 월 17만 개 기록 = 약 2GB/월
  • 14일 보관(binlog_expire_logs_days = 14) = ~1GB

현재 SQL 덤프:

  • 월 1회 ~수백 MB

바이너리 로그가 SQL 덤프보다 훨씬 효율적


7. 검증 및 테스트

7-1. 초기 동기화 확인

복제 시작 후 1시간 기다린 뒤:

-- Synology에서
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master = 0 확인

7-2. 데이터 무결성 확인

기록 저장/삭제를 몇 번 한 뒤 양쪽 DB에서 결과 비교:

-- 운영 DB
SELECT COUNT(*) FROM best_record;
SELECT MAX(BestRecordID) FROM best_record;

-- Synology (5초 뒤)
SELECT COUNT(*) FROM best_record;
SELECT MAX(BestRecordID) FROM best_record;
-- 같아야 함

7-3. 분석 쿼리 확인

Synology에서 무거운 쿼리를 한두 번 실행해보고, 운영 DB에 영향이 없는지 확인:

-- Synology에서 (읽기 전용)
SELECT MaestroID, COUNT(*) FROM best_record GROUP BY MaestroID ORDER BY COUNT(*) DESC LIMIT 10;

-- 동시에 운영 DB의 응답 시간 확인
-- (필요하면 운영 DB에서 `SHOW PROCESSLIST;`)

8. 체크리스트

구현 전

  • 운영 DB의 Binlog 활성화 여부 확인 (SHOW VARIABLES LIKE 'log_bin')
  • Docker 설정 파일 (my.cnf) 위치 파악
  • Synology SSH 접속 가능 확인
  • 현재 backup-db.sh 스크립트 백업
  • Synology의 기존 DB 상태 기록

구현 중

  • 운영 DB에서 복제 계정 생성
  • 마스터 로그 위치 기록 (SHOW MASTER STATUS)
  • Synology에 초기 데이터 복사
  • Synology MariaDB 설정 파일 수정 (server_id, read_only)
  • CHANGE MASTER TO 실행
  • START SLAVE 실행
  • SHOW SLAVE STATUS로 상태 확인

구현 후

  • 1시간 기다린 뒤 Seconds_Behind_Master = 0 확인
  • 기록 저장/삭제 후 양쪽 데이터 일치성 확인
  • 분석 쿼리를 Synology에서 실행해보기
  • backup-db.sh 스크립트 변경 (옵션 선택 시)
  • 모니터링 스크립트 (cron) 설정
  • 정기 백업 확인 (덤프가 Synology에서 정상 생성되는지)

9. 다음 단계

이 문서의 구현이 완료되면:

  1. 안1~안5의 DB 성능 개선병행 가능

    • Replication은 운영 체계 (백업·장애대비)
    • 안1~5는 쿼리 성능 개선
    • 서로 독립적 → 순서 자유
  2. 분석·통계를 Synology에서 안전하게 수행

    • 운영 DB 영향 0
    • 복제본에서만 덤프 (운영 DB 부하 제거)
  3. 장애 시 빠른 복구

    • 복제본이 항상 최신 상태 유지
    • 필요 시 슬레이브를 마스터로 昇格 (선택사항)