비동기 MySQL 복제 설정: 단계별 가이드

이 확실한 단계별 가이드로 비동기 MySQL 복제 설정을 마스터하세요. `my.cnf` 설정 조정, 안전한 복제 사용자 계정 생성, `mysqldump`를 사용한 중요한 초기 데이터 스냅샷 수행을 통해 마스터 및 슬레이브 서버를 올바르게 구성하는 방법을 알아보세요. 이 문서는 확장 가능한 데이터베이스 아키텍처를 위한 효율적인 데이터 동기화를 보장하고 복제 지연을 최소화하는 실용적인 명령어와 필수 문제 해결 팁을 제공합니다.

비동기 MySQL 복제 설정: 단계별 가이드

비동기 MySQL 복제는 여전히 데이터베이스 설정에서 가장 유용한 구성 요소 중 하나입니다. 읽기 복제본, 더 안전한 백업, 보고용 복사본, 마이그레이션 스테이징, 재해 복구에 사용할 수 있습니다. 중요한 단어는 "비동기"입니다. 소스는 복제본이 트랜잭션을 적용할 때까지 기다리지 않고 트랜잭션을 커밋합니다. 이렇게 하면 모든 복제본 쓰기에서 소스가 차단되는 것을 방지할 수 있지만, 복제본이 지연될 수 있음을 의미합니다.

많은 MySQL 명령어에서 사용되는 이전 용어는 "master"와 "slave"입니다. 최신 MySQL 버전은 SHOW REPLICA STATUSCHANGE REPLICATION SOURCE TO와 같은 명령어에서 "source"와 "replica"를 사용합니다. 이전 시스템, 예제 및 스크립트에서 이전 명령어를 여전히 볼 수 있습니다. 이 가이드는 설명에서 source와 replica를 사용하고, 최신 명령어 형식을 먼저 표시하며, 이전 구문이 다른 경우 주석을 추가합니다.

예제에서는 두 대의 서버를 사용합니다:

  • Source: 192.168.1.100
  • Replica: 192.168.1.101
  • 복제 사용자: repl_user
  • 범위: 의도적으로 필터링하지 않는 한 모든 데이터베이스

이 절차를 실행해 본 적이 없다면 먼저 테스트 환경에서 수행하세요. 모든 것이 깨끗할 때 복제 설정은 간단합니다. 소스가 바쁘거나, 덤프가 일관되지 않거나, 복제본에 이미 오래된 데이터가 있는 경우 스트레스가 될 수 있습니다.

설정을 건드리기 전에

기본 사항을 확인하세요:

  • 두 서버 모두 호환되는 MySQL 버전을 실행합니다.
  • 복제본이 MySQL 포트(일반적으로 3306)에서 소스에 도달할 수 있습니다.
  • 두 MySQL 인스턴스에 대한 관리 액세스 권한이 있습니다.
  • MySQL 구성 파일을 편집하고 필요한 경우 MySQL을 다시 시작할 수 있습니다.
  • 복제본이 비어 있거나 교체해야 하는 기존 데이터를 정확히 알고 있습니다.
  • 소스에 바이너리 로그를 위한 충분한 디스크 공간이 있습니다.

복제본 호스트에서 기본 네트워크 액세스를 테스트하세요:

nc -vz 192.168.1.100 3306

nc를 사용할 수 없는 경우 telnet 또는 클라우드 공급자의 연결 도구를 사용하세요. 복제를 구성하기 전에 방화벽, 보안 그룹, 바인드 주소 및 라우팅을 수정하세요. TCP 경로가 차단된 경우 복제 사용자는 도움이 되지 않습니다.

소스 서버 구성

소스는 변경 사항을 바이너리 로그에 기록해야 합니다. 복제본은 이러한 이벤트를 읽고 적용하기 전에 릴레이 로그에 저장합니다.

소스에서 MySQL 구성 파일을 편집하세요. 일반적인 위치는 /etc/mysql/mysql.conf.d/mysqld.cnf, /etc/my.cnf 또는 해당 경로에서 포함된 파일입니다. [mysqld] 아래에 다음 설정을 추가하거나 확인하세요:

[mysqld]
server-id=1
log-bin=mysql-bin
binlog_format=ROW

server-id는 복제 토폴로지의 모든 서버에서 고유해야 합니다. log-bin은 바이너리 로깅을 활성화합니다. binlog_format=ROW는 문 재실행 동작에 의존하지 않고 행 변경을 기록하므로 대부분의 최신 복제 설정에 실용적인 기본값입니다.

binlog-do-dbbinlog-ignore-db를 사용할 때는 주의하세요. 필터링은 편리해 보이지만, 문 기반 동작이 세션에서 선택한 기본 데이터베이스에 따라 달라지기 때문에 예상치 못한 결과를 초래할 수 있습니다. 필터링된 복제가 필요한 경우 의도적으로 설계하고 테스트하세요. 첫 번째 안정적인 설정을 위해서는 모든 것을 복제하세요.

소스에서 MySQL을 다시 시작하세요:

sudo systemctl restart mysql
# 또는 일부 시스템에서는
sudo systemctl restart mysqld

설정을 확인하세요:

SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';

log_binON이어야 합니다. server_id는 0이 아니고 고유해야 합니다.

복제 사용자 생성

복제본이 사용할 소스에 전용 계정을 만드세요. 네트워크 설계가 허용하는 경우 호스트를 복제본 주소로 제한하세요:

CREATE USER 'repl_user'@'192.168.1.101' IDENTIFIED BY 'use_a_real_secret_here';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.1.101';

MySQL 권한에서 권한 이름은 여전히 REPLICATION SLAVE이지만, 최신 문서에서는 다른 곳에서 "replica"라고 말하는 경우가 많습니다.

복제본 호스트에서 로그인을 테스트하세요:

mysql -h 192.168.1.100 -u repl_user -p

실패하면 지금 인증 및 네트워킹을 수정하세요. 일반적인 원인은 소스의 bind-address, 방화벽 규칙, 사용자 호스트 불일치, 다른 주소로 확인되는 DNS, 이전 클라이언트와의 인증 플러그인 비호환성입니다.

복제본 서버 구성

복제본에서 다른 server-id를 구성하세요. 릴레이 로그는 일반적으로 복제를 위해 자동으로 활성화되지만, 명시적으로 이름을 지정하면 작업을 더 명확하게 할 수 있습니다:

[mysqld]
server-id=2
relay_log=mysql-relay-bin
read_only=ON

더 강력한 보호를 위해 설정 후 super_read_only=ON을 고려하세요. read_only는 모든 권한 있는 계정의 쓰기를 막지는 않습니다. super_read_only는 애플리케이션 쓰기를 절대 허용하지 않아야 하는 복제본에 더 안전하지만, 특정 관리 작업을 위해 일시적으로 꺼야 할 수도 있습니다.

복제본에서 MySQL을 다시 시작하고 확인하세요:

sudo systemctl restart mysql
SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES LIKE 'read_only';

일관된 초기 스냅샷 생성

복제본은 특정 바이너리 로그 위치와 일치하는 데이터 복사본으로 시작해야 합니다. 스냅샷과 위치가 일치하지 않으면 복제가 시작되더라도 잘못될 수 있습니다.

InnoDB가 많은 데이터베이스의 경우 mysqldump --single-transaction이 일반적으로 가장 간단한 일관된 방법입니다. 트랜잭션 테이블에 대한 긴 전역 읽기 잠금을 피합니다. 최신 MySQL 버전에서는 --source-data=2를 포함하여 덤프가 소스 바이너리 로그 파일과 위치를 주석 처리된 줄로 기록하도록 합니다. 이전 버전에서는 --master-data=2를 사용합니다.

소스에 연결할 수 있는 신뢰할 수 있는 호스트에서 다음을 실행하세요:

mysqldump -h 192.168.1.100 -u root -p \
  --all-databases \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --source-data=2 \
  > source_dump.sql

MySQL 버전이 --source-data를 지원하지 않는 경우 다음을 사용하세요:

mysqldump -h 192.168.1.100 -u root -p \
  --all-databases \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --master-data=2 \
  > source_dump.sql

--single-transaction은 InnoDB 일관성에 안전하지만, 비트랜잭션 MyISAM 테이블을 같은 방식으로 일관성 있게 만들지는 않습니다. 여전히 MyISAM 테이블이 있는 경우 유지 관리 기간을 계획하거나 일관된 스냅샷을 제공하는 다른 백업 방법을 사용하세요.

덤프에서 기록된 복제 좌표를 확인하세요:

grep -m 1 -E "CHANGE (MASTER|REPLICATION SOURCE)" source_dump.sql

바이너리 로그 파일과 위치가 포함된 주석 처리된 줄이 표시되어야 합니다. 보관하세요. GTID 기반 복제를 선택하지 않는 한 복제본을 소스에 지정할 때 사용합니다.

복제본에 스냅샷 가져오기

일반적인 보안 방법을 사용하여 덤프를 복제본으로 전송하세요:

scp source_dump.sql db-replica:/tmp/source_dump.sql

복제본에서 실수로 기존 프로덕션과 유사한 데이터 세트에 쓰지 않도록 하세요. 이 복제본이 깨끗한 복사본이어야 하는 경우 마이그레이션 계획에서 교체하라고 지정한 것만 삭제하고 다시 만드세요. 그런 다음 가져오기:

mysql -u root -p < /tmp/source_dump.sql

대용량 덤프의 경우 screen 또는 tmux에서 가져오기를 실행하고 디스크 공간을 모니터링하세요. /var/lib/mysql 또는 /tmp가 가득 차서 가져오기가 실패하면 시간이 낭비되고 복제본이 반쯤 로드된 상태로 남을 수 있습니다.

복제본을 소스에 지정

MySQL 8.0.23 이상에서는 CHANGE REPLICATION SOURCE TO를 사용하세요:

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='192.168.1.100',
  SOURCE_USER='repl_user',
  SOURCE_PASSWORD='use_a_real_secret_here',
  SOURCE_LOG_FILE='mysql-bin.000001',
  SOURCE_LOG_POS=1234;

파일과 위치를 덤프의 값으로 바꾸세요. 이전 구문을 사용하는 경우 동등한 것은 다음과 같습니다:

CHANGE MASTER TO
  MASTER_HOST='192.168.1.100',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='use_a_real_secret_here',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=1234;

환경에서 GTID를 사용하는 경우 설정이 다릅니다. 일반적으로 두 서버에서 GTID 모드를 구성하고, GTID 상태를 유지하는 덤프를 복원하고, 파일 및 위치 대신 SOURCE_AUTO_POSITION=1을 사용합니다. GTID와 파일-위치 지침을 무심코 혼합하지 마세요. 한 가지 접근 방식을 선택하고 테스트하세요.

GTID 복제에 대한 간단한 참고 사항

GTID 복제는 MySQL이 전역 트랜잭션 ID로 트랜잭션을 추적하므로 설정 후 운영하기가 더 쉬운 경우가 많습니다. 장애 조치, 소스 변경 및 복제본 재구축 중에 특히 유용합니다.

그렇다고 해서 마이그레이션 중간에 무심코 켜야 한다는 의미는 아닙니다. 두 서버 모두 호환되는 GTID 설정이 필요하며, 백업 또는 덤프 프로세스가 올바른 GTID 상태를 유지해야 합니다. 일반적인 패턴은 다음과 같이 구성하는 것입니다:

[mysqld]
gtid_mode=ON
enforce_gtid_consistency=ON

그런 다음 GTID 인식 덤프를 복원한 후 다음을 사용하여 복제본을 구성하세요:

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='192.168.1.100',
  SOURCE_USER='repl_user',
  SOURCE_PASSWORD='use_a_real_secret_here',
  SOURCE_AUTO_POSITION=1;

소스와 복제본의 GTID 기록이 깨끗하고 이해된 경우에만 사용하세요. 확실하지 않은 경우 파일 및 위치 복제가 첫 번째 설정에 대해 추론하기 더 쉽습니다. 최악의 선택은 복제가 시작될 때까지 두 접근 방식의 예제를 혼합하는 것이지만 트랜잭션 기록이 생각한 대로가 아닙니다.

복제 시작:

START REPLICA;

이전 구문:

START SLAVE;

상태 확인:

SHOW REPLICA STATUS\G

이전 구문:

SHOW SLAVE STATUS\G

주요 필드는 다음과 같습니다:

필드 정상 값 설명
Replica_IO_Running Yes 복제본이 연결하고 바이너리 로그 이벤트를 가져올 수 있습니다.
Replica_SQL_Running Yes 복제본이 릴레이 로그 이벤트를 적용할 수 있습니다.
Last_IO_Error 비어 있음 네트워크, 자격 증명 또는 소스 로그 문제가 여기에 표시됩니다.
Last_SQL_Error 비어 있음 데이터 충돌 및 적용 오류가 여기에 표시됩니다.
Seconds_Behind_Source 낮거나 감소 중 대략적인 지연 표시기입니다.

이전 출력은 Slave_IO_Running, Slave_SQL_RunningSeconds_Behind_Master를 사용합니다.

작은 쓰기로 테스트

스레드가 Yes라고 말한 후에 승리를 선언하지 마세요. 소스에 작은 테스트 테이블을 만들거나 기존 테스트 스키마에 무해한 행을 삽입한 다음 복제본에 나타나는지 확인하세요.

소스 예제:

CREATE DATABASE IF NOT EXISTS repl_check;
CREATE TABLE IF NOT EXISTS repl_check.heartbeat (
  id INT PRIMARY KEY,
  checked_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
REPLACE INTO repl_check.heartbeat (id) VALUES (1);

복제본에서:

SELECT * FROM repl_check.heartbeat;

이렇게 하면 잘못된 소스를 가리키거나, 데이터베이스를 필터링하거나, 오래된 좌표를 사용하는 등의 간단한 실수를 잡을 수 있습니다.

복제 채널 보안

복제 트래픽이 신뢰할 수 없는 네트워크를 통과하는 경우 TLS가 필요합니다. 사설 네트워크 내에서도 많은 팀이 네트워크 경계가 시간이 지남에 따라 변경되므로 암호화된 데이터베이스 트래픽을 선호합니다.

최소한 복제 사용자와 채널을 만들어 자격 증명이 애플리케이션 계정과 공유되지 않도록 하세요. TLS 기반 채널의 경우 MySQL 버전에 따라 인증서를 구성한 다음 복제 소스 구성에 SSL 옵션을 포함하세요. 정확한 옵션은 버전 및 인증서 정책에 따라 다르지만 의도는 동일합니다. 복제본이 예상된 소스에 연결하고 있는지 확인하고 전송 중인 자격 증명과 행 변경을 보호해야 합니다.

또한 복제 사용자의 권한을 좁게 유지하세요. 광범위한 DDL 또는 DML 액세스가 필요하지 않습니다. 누군가 해당 암호를 얻으면 폭발 반경은 복제 로그 읽기로 제한되어야 하며 애플리케이션 데이터를 쓰지 않아야 합니다.

일반적인 설정 문제

Replica_IO_RunningNo인 경우 복제본이 이벤트를 가져올 수 없습니다. 확인:

  • SOURCE_HOST가 올바릅니다.
  • 소스가 예상된 주소와 포트에서 수신 대기 중입니다.
  • 방화벽 및 보안 그룹이 트래픽을 허용합니다.
  • 복제 사용자 호스트가 복제본의 소스 IP와 일치합니다.
  • 암호 및 인증 플러그인이 복제본의 클라이언트/서버 버전과 작동합니다.
  • 요청된 바이너리 로그 파일이 소스에 여전히 존재합니다.

Replica_SQL_RunningNo인 경우 복제본이 이벤트를 가져왔지만 적용할 수 없습니다. Last_SQL_Error를 확인하세요. 중복 키는 종종 복제본이 정확히 일치하는 스냅샷으로 초기화되지 않았거나 누군가가 복제본에 직접 썼음을 의미합니다. 누락된 행은 종종 데이터 드리프트를 의미합니다. SQL_SLAVE_SKIP_COUNTER로 트랜잭션을 건너뛰면 스레드가 움직일 수 있지만 복제본이 잘못될 수도 있습니다. 실패한 트랜잭션을 이해하고 발산 위험을 수용하는 경우에만 사용하세요.

설정 직후 지연이 높은 경우 복제본이 따라잡도록 하고 Seconds_Behind_Source가 떨어지는지 확인하세요. 대용량 덤프 가져오기 후 복제 시작은 백로그를 남길 수 있습니다. 지연이 줄어들지 않고 증가하는 경우 복제본의 디스크 I/O와 소스의 쓰기 볼륨을 검사하세요.

설정 후 복제본 상태 유지

복제본이 유지 관리 및 중단 시간을 견딜 수 있도록 소스에서 바이너리 로그 보존을 구성하세요. 최신 MySQL은 binlog_expire_logs_seconds를 사용합니다:

[mysqld]
binlog_expire_logs_seconds=604800

이 예제는 로그를 약 7일 동안 유지합니다. 복구 요구 사항과 디스크 용량에 따라 값을 선택하세요. 이전 시스템은 expire_logs_days를 사용할 수 있습니다.

복제 상태와 지연을 모니터링하세요. 최소한 복제 스레드 중 하나가 중지되거나, 지연이 허용 한도를 초과하거나, 바이너리 로그가 제거되지 않아 소스 디스크 사용량이 증가할 때 경고하세요. 데이터 일관성 검사를 위해 많은 팀이 Percona Toolkit 도구(예: pt-table-checksumpt-table-sync)를 사용하지만, 프로덕션 규모 데이터에서 실행하기 전에 신중하게 테스트하세요.

마지막으로, 복제본이 읽기 전용이고, 따라잡았으며, 모니터링되고 있다고 확신할 때까지 애플리케이션 트래픽을 복제본에서 멀리 유지하세요. 실수로 쓰기를 수락하는 복제본은 복제본이 없는 것보다 더 나쁩니다. 장애 조치 또는 복구까지 손상이 숨겨져 있을 수 있기 때문입니다.

비동기 복제는 시작 스냅샷, 바이너리 로그 좌표, 권한 및 모니터링이 모두 일치할 때 잘 작동합니다. 대부분의 실패한 설정은 이러한 것 중 하나가 확인되지 않고 가정되었기 때문에 발생합니다.