비동기 MySQL 복제 설정: 단계별 가이드
MySQL 복제는 고가용성, 확장성, 견고한 백업 전략을 달성하기 위한 필수적인 기능입니다. 가장 일반적인 유형인 비동기 복제는 마스터 서버(Master)에 기록된 데이터가 슬레이브 서버(Slave)가 트랜잭션을 확인하기를 기다리지 않고 하나 이상의 보조 서버(Slaves)에 결국 복사되도록 보장합니다.
이 포괄적인 가이드는 MySQL을 사용하여 표준 마스터-슬레이브 비동기 복제 설정을 구성하기 위한 상세한 단계별 튜토리얼을 제공합니다. 필요한 서버 구성 조정, 사용자 설정, 그리고 데이터 동기화를 초기화하기 위한 중요한 단계를 다룰 것입니다.
전제 조건 및 개요
구성을 시작하기 전에 다음 사항을 확인하십시오:
- 작동 중인 두 대의 MySQL 서버 (서버 A: 마스터, 서버 B: 슬레이브).
- 두 서버 간의 네트워크 연결 (일반적으로 TCP 포트 3306이 열려 있어야 함).
- 두 MySQL 인스턴스를 구성하고
my.cnf또는my.ini구성 파일을 수정하기 위한 루트 또는 관리자 액세스 권한.
본 가이드의 목적으로, 마스터 서버 IP는 192.168.1.100, 슬레이브 서버 IP는 192.168.1.101이라고 가정합니다.
1단계: 마스터 서버 구성
마스터 서버는 모든 데이터 수정 이벤트를 바이너리 로그 파일에 기록하도록 구성되어야 하며, 슬레이브는 이 파일을 읽게 됩니다.
1단계: 마스터 구성 파일 편집 (my.cnf)
MySQL 구성 파일 (일반적으로 /etc/mysql/my.cnf 또는 /etc/my.cnf)을 찾아 [mysqld] 섹션 내에 다음 지시문을 추가하거나 수정하십시오.
[mysqld]
# 1. 이 서버의 고유 ID (0보다 커야 함)
server-id=1
# 2. 바이너리 로깅 활성화
log-bin=mysql-bin
# 3. 복제할 데이터베이스 목록 (선택 사항이지만 권장됨)
# binlog-do-db=mydatabase
# 4. 선택 사항: 연결이 TCP/IP를 사용하도록 보장 (테스트에 유용)
# bind-address=0.0.0.0
참고:
server-id는 복제 토폴로지에 참여하는 모든 서버에서 고유해야 합니다.
2단계: MySQL 재시작 및 바이너리 로깅 확인
구성 파일을 저장한 후 마스터 서버에서 MySQL 서비스를 재시작하십시오.
# Debian/Ubuntu
sudo systemctl restart mysql
# RHEL/CentOS
sudo systemctl restart mysqld
MySQL 명령줄 인터페이스에 로그인하여 바이너리 로깅이 활성화되었는지 확인하십시오:
SHOW VARIABLES LIKE 'log_bin';
-- 값은 ON이어야 합니다.
3단계: 복제 사용자 생성
복제에는 슬레이브가 연결하고 바이너리 로그를 검색하는 데 사용할 특정 권한을 가진 마스터 서버의 전용 사용자 계정이 필요합니다. 이 사용자가 슬레이브의 IP 주소(192.168.1.101)에서 원격으로 연결할 수 있는지 확인하십시오.
CREATE USER 'repl_user'@'192.168.1.101' IDENTIFIED BY 'secure_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.1.101';
FLUSH PRIVILEGES;
4단계: 현재 마스터 상태 기록
진행하기 전에 슬레이브가 읽기 시작해야 하는 바이너리 로그 내의 정확한 위치(파일 및 위치)를 설정해야 합니다. 이 단계는 동기화에 매우 중요합니다.
FLUSH TABLES WITH READ LOCK; -- 일시적으로 쓰기를 중단합니다.
SHOW MASTER STATUS;
-- 중요: 다음 두 값을 기록해 두십시오.
-- File: mysql-bin.000001
-- Position: 1234
-- 초기 스냅샷을 찍는 경우 (6단계) 테이블 잠금을 아직 해제하지 마십시오.
2단계: 슬레이브 서버 구성
5단계: 슬레이브 구성 파일 편집 (my.cnf)
고유 ID 및 선택적 설정을 사용하여 슬레이브 서버를 구성하십시오.
[mysqld]
# 이 서버의 고유 ID (마스터와 달라야 함)
server-id=2
# 선택 사항: 안전을 위해 권장됨
read_only=1
# 선택 사항: 릴레이 로깅 활성화
relay_log=mysql-relay-bin
변경 사항을 저장한 후 슬레이브 서버에서 MySQL 서비스를 재시작하십시오.
6단계: 초기 데이터 전송 (스냅샷)
슬레이브 서버가 비어 있는 경우, 마스터의 현재 데이터 구조와 내용으로 슬레이브를 채워야 합니다. 이 초기 스냅샷은 마스터 테이블이 잠겨 있는 동안(4단계에서) 찍어야 합니다.
마스터 서버에서 mysqldump 명령을 실행하십시오. 덤프 파일에 필요한 CHANGE MASTER TO 문을 자동으로 포함시키기 위해 --master-data=2 플래그를 사용하며, 이는 7단계를 단순화합니다.
# 마스터 서버 콘솔/쉘에서 실행
mysqldump -u root -p --all-databases --master-data=2 --single-transaction > master_dump.sql
# 이제 마스터 MySQL CLI로 돌아가 잠금을 해제합니다.
UNLOCK TABLES;
master_dump.sql을 슬레이브 서버로 전송하고 가져오기(import)하십시오:
# 슬레이브 서버 콘솔/쉘에서 실행
mysql -u root -p < master_dump.sql
모범 사례:
master-data=2를 사용하면 덤프 시작 시점에 올바른 바이너리 로그 위치 캡처가 자동화되므로 강력히 권장됩니다.
3단계: 복제 시작
7단계: 마스터 연결 정의
슬레이브 서버의 MySQL 명령줄에서 4단계에서 기록한 값과 3단계에서 생성한 사용자를 대체하여 CHANGE MASTER TO 명령을 실행하십시오.
CHANGE MASTER TO
MASTER_HOST='192.168.1.100',
MASTER_USER='repl_user',
MASTER_PASSWORD='secure_password',
MASTER_LOG_FILE='mysql-bin.000001', -- 4단계에서 기록된 파일
MASTER_LOG_POS=1234; -- 4단계에서 기록된 위치
8단계: 복제 시작 및 확인
연결 매개변수를 정의한 후 슬레이브의 복제 스레드를 시작하십시오.
START SLAVE;
SHOW SLAVE STATUS 명령을 사용하여 복제 스레드가 올바르게 실행되고 통신하는지 확인하십시오:
SHOW SLAVE STATUS\G
다음 중요 필드를 출력에서 검토하십시오:
| 필드 | 예상 값 | 설명 |
|---|---|---|
Slave_IO_Running |
Yes |
슬레이브가 마스터에 성공적으로 연결 중입니다. |
Slave_SQL_Running |
Yes |
슬레이브가 데이터베이스에 트랜잭션을 적용 중입니다. |
Seconds_Behind_Master |
0 또는 낮은 숫자 |
복제 지연 시간을 나타냅니다. 빠르게 0으로 떨어져야 합니다. |
Slave_IO_Running 또는 Slave_SQL_Running 중 하나라도 No로 표시되면, 문제 해결 단서(예: 방화벽 문제, 잘못된 자격 증명, 중복 키)를 위해 Last_IO_Error 또는 Last_SQL_Error 필드를 확인하십시오.
문제 해결 및 유지 관리 팁
복제 오류 처리
슬레이브가 오류(예: 중복 기본 키 삽입 시도)를 만나면 Slave_SQL_Running 스레드가 중지됩니다. 일반적으로 사소하고 중요하지 않은 오류는 다음을 사용하여 우회할 수 있습니다.
STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START SLAVE;
경고:
SQL_SLAVE_SKIP_COUNTER는 신중하게 사용하십시오. 트랜잭션을 건너뛰면 마스터와 슬레이브 간에 데이터 불일치(divergence)가 발생할 수 있습니다.
일관성 확인
비동기 복제는 효율적이지만 즉각적인 일관성을 보장하지는 않습니다. 중요도가 높은 환경에서는 Percona Toolkit의 pt-table-checksum과 같은 도구를 활용하여 마스터와 슬레이브 간의 데이터 드리프트(data drift)를 주기적으로 확인하십시오.
바이너리 로그 관리
바이너리 로그는 시간이 지남에 따라 디스크 공간을 소비합니다. 디스크 과용을 방지하기 위해 마스터에서 로그 만료를 구성하십시오.
[mysqld]
# 7일(604800초)보다 오래된 바이너리 로그를 제거합니다.
expire_logs_days=7