백은빈, 이성욱 님의 "Real MySQL" 책을 정리한 포스팅 입니다.
- 소스 서버의 바이너리 로그에 기록된 변경내역들을 식별하는 방식에 따라 나뉨
1. 바이너리 로그 파일 위치 기반 복제
- 소스 서버의 바이너리 로그 파일명과 파일 내에서의 위치로 개별 바이너리 로그 이벤트를 식별해서 복제함
- 이벤트 하나하나를 바이너리 로그 파일명과 파일내에서의 위치값의 조합으로 식별함
- 레플레카 서버에서 소스 서버의 어떤 이벤트부터 동기화를 수행할 것인지 설정해야 함
- 어느 이벤트까지 로컬 디스크로 가져왔고 적용했는지 관리
- 다음번에 가져올 이벤트를 표시하려는 목적
필수 사항
- 복제 구성원이 되는 MySQL 서버가 고유의 server_id를 가지고 있어야 함
- 소스 서버에서 반드시 바이너리 로그가 활성화돼 있어야 함
- 기본적으로 활성화 되어 있음
- 서버 시작 시 데이터 디렉터리 밑에 "binlog"라는 이름으로 자동으로 생성됨
실습
소스 서버 설정
[mysqld]
server_id=1 # 기본값 1
sync_binlog=1
binlog_cache_size=5M
max_binlog_size=512M
binlog_expire_logs_seconds=1209600
- server_id: 레플리케이션 시, 노드를 구분하는 유일값
- sync_binlog: 바이너리 로그를 디스크에 동기화하는 주기를 설정
- 1: 트랜잭션이 커밋될 때마다 디스크에 즉시 기록
- 0: 운영체제가 캐시한 후 비동기적으로 기록
- N: N개의 트랜잭션마다 1번 동기화
- binlog_cache_size: 바이너리 로그 캐시의 크기를 설정하는 값
- 바이너리 로그에 기록될 내용을 메모리에 캐싱하고, 커밋 시 디스크에 기록
- max_binlog_size: 단일 바이너리 로그 파일의 최대 크기
- binlog_expire_logs_seconds: 바이너리 로그를 자동으로 삭제하는 주기 (초 단위)
레플리카 서버 설정
[mysqld]
server_id=2
relay_log=/relay-log/path/relay-log-name
relay_log_purge=ON
read_only
log_slave_updates
- relay_log: 릴레이 로그가 저장될 경로 및 파일 이름
- relay_log_purge: 릴레이 로그가 레플리카 서버 리포지토리에 반영될 경우, 릴레이 로그 파일 자동 삭제
- log_slave_updates: 레플리카 서버가 소스 서버로 승격될 경우, 갱신 작업
복제 계정 준비
CREATE USER 'repl'@'%' IDENTIFIED BY 'replpassword';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
- 레플리카 서버가 소스 서버로부터 바이너리 로그를 가져오려면 접속 계정이 있어야 함
소스 서버: 데이터 덤프 (mysqldump)
mysqldump -u root -p \
--all-databases --single-transaction --flush-logs --master-data=2 > backup.sql
- --single-transaction
- 데이터를 덤프할 때 하나의 트랜잭션을 사용해서 덤프
- 테이블이나 레코드에 잠금을 걸지 않고 일관된 데이터를 덤프받도록 함
- --master-data
- 덤프 시작 시점에 복제 설정 구문이 덤프 파일 헤더에 기록될 수 있게 하는 옵션 (바이너리 로그 파일명, 위치정보)
- "FLUSH TABLE WITH READ LOCK"으로 글로벌 락을 검 (바이너리 로그 파일의 위치를 고정시키기 위함)
레플리카 서버: 데이터 복사
mysql> SOURCE /tmp/backup.sql # 레플리카 서버에 덤프 파일이 있다 가정
- 소스 서버의 덤프 파일을 레플리카 서버로 옮기기
복제 시작
- 소스 서버의 바이너리 로그 정보 확인
- show master status;
- File, Position
change replication source to
source_host='127.0.0.1',
source_port=3306,
source_user='repl',
source_password='password!',
source_log_file='binlog.000246',
source_log_pos=826,
get_source_public_key=1;
- 레플리카 서버) 소스 서버 정보 셋팅
start replica;
- 레플리카 서버) 복제 명령 실행
show replica status;
*************************** 1. row ***************************
Replica_IO_State: Waiting for source to send event
Source_Host: 192.168.35.179
Source_User: repl
Source_Port: 3306
Connect_Retry: 60
Source_Log_File: binlog.000247
Read_Source_Log_Pos: 156
Relay_Log_File: mysql-relay-bin.000003
Relay_Log_Pos: 366
Relay_Source_Log_File: binlog.000247
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Source_Log_Pos: 156
Relay_Log_Space: 741
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Source_SSL_Allowed: No
Source_SSL_CA_File:
Source_SSL_CA_Path:
Source_SSL_Cert:
Source_SSL_Cipher:
Source_SSL_Key:
Seconds_Behind_Source: 0
Source_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Source_Server_Id: 1
Source_UUID: b06df802-6ea5-11ea-9ec3-edc515152da1
Source_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates
Source_Retry_Count: 86400
Source_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Source_SSL_Crl:
Source_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Source_TLS_Version:
Source_public_key_path:
Get_Source_public_key: 0
Network_Namespace:
- 레플리카 서버) 복제 상태 확인
- Replica_IO_Running과 Replica_SQL_Running 값이 "YES" 이면 동기화 된것임
트랜잭션 건너뛰기
- 종종 소스서버로부터 넘어온 트랜잭션이 레플리카 서버에서 제대로 실행되지 못하고 에러가 발생함
- 단 이런경우는 트랜잭션 자체가 잘못되었을 경우가 많음
- 이러한 경우 트랜잭션을 무시하고 넘어갈 수 있음
- sql_slave_skip_count 시스템 변수를 1로 설정하고 SQL_THREAD를 재시작
- 지정한 숫자는 무시할 이벤트 그룹 수를 의미함
- 현재 처리중인 이벤트 그룹의 모든 이벤트 무시
2. 글로벌 트랜잭션 아이디 기반 복제
바이너리 로그 파일 위치 기반 복제의 문제점
- 레플리카 서버들이 같은 이벤트에 대해 서로 다른 식별값을 가짐
- 이로 인해 복제 토폴로지를 변경하는 작업은 불가능함
- 복제 토폴로지 변경은 레플리카 서버들 중 장애가 발생하였을 때 필요함
- 즉, 장애 복구가 어려움
GUID
- 모든 레플리카 서버들이 각 이벤트들에 대해 동일하게 부여된 고유 식별값
- 이를 기반으로 복제가 진행됨
필요성
- 레플리카 서버 중 한 서버가 지연이 발생해 동기화가 60%까지 진행됨
- 이때 소스 서버에서 장애가 발생하여 비정상적으로 종료됨
- 그러면 완전히 동기화된 레플리카 서버가 소스 서버로 승격함
- 이렇게 되면 완전히 동기화되지 않은 레플리카 서버에서 부하 분산용으로 트래픽을 처리할 경우 모순이 일어남
동작 방식
- 특정 레플리카 서버가 승격되면, 완전히 동기화되지 않은 레플리카 서버는 승격된 서버를 대상으로 동기화를 시도함
- 이 떄, 승격된 레플리카에서 사용중인 로그 파일을 알 필요 없음
구성
- 서버에서 커밋된 각 트랜잭션과 연결된 고유 식별자
- SELECT 쿼리나 sql_log_bin 설정이 비활성화 돼있는 상태에서 발생한 트랜잭션은 할당되지 않음
- 소스 아이디와 트랜잭션 아이디 값의 조합 (콜론으로 구분됨)
- 소스 아이디: 트랜잭션이 발생된 소스 서버 식별값 (server_uuid 시스템 값)
- 트랜잭션 아이디: 서버에서 커밋된 트랜잭션 순서대로 부여되는 값 (1씩 증가하는 형태)
확인
select * from mysql.gtid_executed;
실습
다음 장에 계속...
'Database > Mysql' 카테고리의 다른 글
[업무에 바로 쓰는 SQL 튜닝] 2. SQL 튜닝 용어를 직관적으로 이해하기 (3) | 2025.03.18 |
---|---|
[업무에 바로 쓰는 SQL 튜닝] 1. MySQL과 MariaDB 개요 (0) | 2025.03.18 |
[Real MySQL] 14-2. 스토어드 프로그램: 참고사항 (0) | 2025.03.13 |
[Real MySQL] 14-1. 스토어드 프로그램: 기본 (1) | 2025.03.13 |
[Real MySQL] 13-2. 파티션: 종류 (0) | 2025.03.13 |