InnoDB Cluster 3부작
1. Group Replication (1) - 개념 이해하기
2. Group Replication (2) - 구성하기
3. MySQL InnoDB Cluster Metadata 생성 및 MySQL Router 구성하기
목차
1. 그룹 복제 아키텍처
MySQL 그룹복제는 서로 다른 호스트 머신에서 실행될 수도, 같은 호스트 머신에서 다른 인스턴스 여러개로 구성할수도 있습니다.
해당 글에서는 일반적으로 많이 사용되는 다른 호스트 머신에서 실행되는 각각의 인스턴스로 그룹 복제를 구성해보겠습니다.
세 개의 서버 인스턴스 S1, S2, S3이 하나의 그룹으로 구성되며, 클라이언트는 각 서버 인스턴스와 통신할 수 있습니다.
각 서버의 역할은 다음과 같습니다.
서버 | Hostname | IP | 역할 |
S1 | S1-192-168-1-11 | 192.168.1.11 | 그룹 최초 합류 서버 |
S2 | S2-192-168-1-12 | 192.168.1.12 | - |
S3 | S3-192-168-1-13 | 192.168.1.13 | - |
2. 그룹 복제 사전 세팅하기
1) 스토리지 엔진 설정
그룹 복제에서는 InnoDB 트랜잭션 스토리지 엔진을 사용해야 합니다
MEMORY 스토리지 엔진을 포함한 다른 스토리지 엔진을 사용할 경우 그룹 복제에서 오류가 발생할 수 있습니다.
만일 다른 스토리지 엔진을 사용하는 개체가 있다면 InnoDB로 변경 후 그룹 복제를 구성해야합니다.
다른 스토리지 엔진을 사용하여 발생하는 문제를 disabled_storage_engines 시스템 변수에 InnoDB를 제외한 스토리지 엔진을 설정하여 사전에 방지할 수 있습니다.
# my.cnf에 추가
[mysqld]
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
disabled_storage_engines 변수는 Dynamic을 지원하지 않으므로 my.cnf 수정이 필요합니다.
※ 주의
MySQL8.0.16 이하 버전에서 disabled_storage_engines 에 MyISAM이 등록된 상태에서 mysql_upgrade 명령을 수행할 경우 오류가 발생할 수 있습니다.
만일 mysql_upgrade를 수행할 일이 있다면 disabled_storage_engines 에서 MyISAM을 제외하고 작업한 다음, 원래대로 변경하는 방법을 권장합니다.
2) 그룹 복제 설정
그룹의 모든 노드에서 MySQL 설정파일(my.cnf, my.ini) 수정이 필요합니다.
[mysqld]
server_id=1 # 서버마다 다르게 설정
gtid_mode=ON
enforce_gtid_consistency=ON
plugin_load_add='group_replication.so'
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" # 그룹 UUID
group_replication_start_on_boot=off
group_replication_local_address="192.168.1.11:33061" # 서버마다 다르게 설정
group_replication_group_seeds="192.168.1.11:33061,192.168.1.12:33061,192.168.1.13:33061"
group_replication_bootstrap_group=off
- server_id
그룹 내 멤버간 server_id를 각각 다른 값으로 설정해야합니다. - gtid_mode = ON
그룹 복제에서는 GTID를 이용하여 복제를 수행하므로 활성화되어있어야 합니다. - enforce_gtid_consistency=ON
GTID 일관성을 위반하지 않은 쿼리문만 사용될 수 있도록 합니다. - plugin_load_add='group_replication.so'
그룹 복제 플러그인을 서버 시작 시 로드하도록 합니다.
실제 운영 환경에서는 수동으로 플러그인을 설치하는 것 보다 이 방법이 권장됩니다. - group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
그룹 복제 플러그인에 그룹 이름을 설정합니다.
이 값은 유효한 UUID여야 하며, SELECT UUID(); 로 UUID를 생성할 수도 있습니다. - group_replication_start_on_boot=off
서버 시작 시 자동으로 그룹복제가 시작되지 않도록 합니다. - group_replication_local_address="192.168.1.11:33061"
그룹 내 다른 멤버들과의 통신을 위해 자신의 네트워크 주소와 포트를 설정합니다.
이 값은 MySQL 클라이언트 연결주소(ex. 3306포트)와 달라야 합니다.
IPV4뿐만 아니라 IPV6 주소도 지원하며, 기본적으로 33061 포트 사용을 권장합니다. - group_replication_group_seeds="192.168.1.11:33061,192.168.1.12:33061,192.168.1.13:33061"
새로운 멤버가 그룹에 연결할 때 사용할 시드 멤버 목록을 설정합니다.
여기서 설정하는 hostname:port 값은 각 멤버가 설정한 group_replication_local_address와 동일해야 합니다. - group_replication_bootstrap_group=off
그룹 부트스트랩을 비활성화합니다.
설정 파일에는 off로 설정하고, 인스턴스 실행 중에 사용자가 쿼리로 직접 제어하는 방식을 권장합니다.
group_replication_bootstrap_group
이 시스템 변수는 그룹의 부트스트랩(초기화) 여부를 결정합니다.
하나의 서버 인스턴스에서만 활성화해야하며, 그룹을 처음 시작/재시작 하는 경우에 사용합니다.
이 변수를 여러 서버에서 동시에 활성화 할 경우, 동일한 이름을 가진 두개의 다른 그룹이 존재하는 스플릿 브레인 현상이 발생할 수 있습니다.
따라서 첫 번재 서버 인스턴스의 group_replication_bootstrap_group을 on으로 설정하여 그룹이 온라인 상태가 된 후에는 반드시 off 로 바꾸어야 합니다.
싱글-프라이머리 모드에서는 group_replication_bootstrap_group=on 작업을 수행하는 서버가 최초의 프라이머리 서버가 됩니다.
MySQL 8.0.3 이하, 8.0.20 이하 버전에서는 아래와 같은 추가 설정이 필요합니다.
[mysqld]
# MySQL 8.0.20 이하 버전일 경우 설정
binlog_checksum=NONE
# MySQL 8.0.3 이하 버전일 경우 설정
log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE
transaction_write_set_extraction=XXHASH64
3) 그룹 복제 모드 설정 (싱글 프라이머리/ 멀티 프라이머리)
group_replication_single_primary_mode 시스템변수를 통해 그룹복제 모드를 제어할 수 있습니다.
해당 변수에 특별한 설정값이 없는경우 기본값은 ON이 되며, 이는 싱글 프라이머리 모드를 의미합니다.
group_replication_single_primary_mode=ON으로 설정하면 그룹 복제를 멀티 프라이머리 모드로 설정할 수 있습니다.
그룹 내 모든 멤버의 group_replication_single_primary_mode 시스템 변수는 같아야 합니다.
즉, 멀티 프라이머리 모드로 구축하려면 group_replication_single_primary_mode이 모든 멤버에서 OFF로 설정되어야 하며 싱글 프라이머리 모드로 구축하려면 group_replication_single_primary_mode이 모든 멤버에게서 ON으로 설정되어야 합니다.
[mysqld]
group_replication_single_primary_mode = OFF # 그룹 복제를 멀티 프라이머리 모드로 설정
group_replication_single_primary_mode 변수는 Dynamic을 지원하므로 아래와 같이 명령으로도 제어가능합니다.
-- 그룹 복제를 싱글 프라이머리 모드로 설정
SET GLOBAL group_replication_single_primary_mode =ON;
-- 그룹 복제를 멀티 프라이머리 모드로 설정
SET GLOBAL group_replication_single_primary_mode =OFF;
3. 그룹 복제 사용자 설정
그룹 복제(Group Replication)는 그룹에 멤버를 추가할 때 동기화를 수행하기 위해 분산 복구(Distributed Recovery) 프로세스를 사용합니다.
분산 복구는 group_replication_recovery라는 복제 채널을 사용하여 기증자(donor)의 바이너리 로그로 합류하는 멤버에게 트랜잭션을 전송하는 과정입니다. 따라서 그룹 복제 설정 시 멤버 간 직접적인 복제 채널을 구성할 수 있도록 적절한 권한을 가진 계정을 생성해야 합니다.
모든 그룹 멤버는 동일한 복제 사용자를 분산 복구에 사용해야 합니다.
계정을 생성하는 과정은 바이너리 로그에 기록될 수 있으며, 이 경우 사용자 생성 명령이 그룹 내 다른 서버로 자동 복제됩니다.
이를 방지하고 싶다면 계정 생성 전 바이너리 로깅을 비활성화한뒤 계정 생성이 완료되면 로깅을 활성화해야합니다.
1) 그룹 복제 사용자 계정 생성
- MySQL 서버 인스턴스를 시작하고 클라이언트로 연결
MySQL 서버를 실행한 후, 클라이언트로 접속합니다. - 필요 시 바이너리 로깅 비활성화 (선택 사항)
복제 사용자를 각 인스턴스에서 개별적으로 생성하려면, 바이너리 로깅을 비활성화합니다.
SET SQL_LOG_BIN=0;
- 그룹 복제 계정 생성 및 권한 부여
아래와 같은 권한을 가진 계정을 생성합니다.
- REPLICATION SLAVE
- CONNECTION_ADMIN
- BACKUP_ADMIN
- GROUP_REPLICATION_STREAM
CREATE USER 'rpl_user'@'%' IDENTIFIED BY 'password'; GRANT REPLICATION SLAVE ON *.* TO 'rpl_user'@'%'; GRANT CONNECTION_ADMIN ON *.* TO 'rpl_user'@'%'; GRANT BACKUP_ADMIN ON *.* TO 'rpl_user'@'%'; GRANT GROUP_REPLICATION_STREAM ON *.* TO 'rpl_user'@'%'; FLUSH PRIVILEGES;
- 바이너리 로깅 재활성화 (선택 사항)
SET SQL_LOG_BIN=1;
- 그룹 복제 계정 등록
MySQL 8.0.23 이상에서는 CHANGE REPLICATION SOURCE TO 문을 사용하고, MySQL 8.0.23 이전 버전에서는 CHANGE MASTER TO 문을 사용하여 group_replication_recovery 채널의 계정을 등록할 수 있습니다.
# MySQL 8.0.23 이상 버전 CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery'; # MySQL 8.0.23 이전 버전 CHANGE REPLICATION SOURCE TO SOURCE_USER='rpl_user', SOURCE_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';
4. 그룹 복제 플러그인 설치
그룹복제를 구성하기 위해서는 그룹복제 플러그인이 필요합니다.
위에서 설명하였듯 그룹복제 플러그인은 옵션파일이나, INSTALL 구문을 사용하여 설치할 수 있습니다
my.cnf 옵션파일에서 plugin_load_add='group_replication.so' 을 사용했다면 플러그인이 이미 설치된 상태입니다.
# 설정파일에서 group_replication.so 플러그인 설치
[mysqld]
plugin_load_add='group_replication.so'
# INSTALL 구문으로 group_replication.so 플러그인 수동 설치
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
# 설치된 플러그인 확인
SHOW PLUGINS;
SELECT * FROM information_schema.PLUGINS WHERE PLUGIN_NAME = 'group_replication';
5. 그룹 부트스트래핑
그룹을 처음 시작하는 과정을 부트스트래핑(Bootstrapping)이라고 합니다.
MySQL에서는 group_replication_bootstrap_group 시스템 변수를 사용하여 그룹을 부트스트랩 할 수 있습니다.
부트스트랩은 그룹을 시작하는 하나의 서버에서 한 번만 수행되어야 하기 때문에 group_replication_bootstrap_group 변수는 설정 파일(my.cnf, my.ini)에서 반드시 off로 설정되어야 합니다.
만약 설정 파일에 변수가 on으로 저장된다면, 서버가 재시작될 때 동일한 이름의 두 번째 그룹이 자동으로 부트스트랩됩니다.
이 경우 동일한 이름을 가진 두 개의 개별 그룹이 생성되는 문제가 발생합니다. 또한 이 옵션을 ON으로 설정한 상태에서 플러그인을 중지하고 다시 시작하는 것도 문제를 일으킬 수 있습니다.
따라서 그룹을 안전하게 부트스트랩하려면 설정파일에서 제어하지 않고, 클라이언트에서 쿼리로 활성화해야 합니다.
위에서 설명했던것 처럼 S1(192.168.1.11)을 최초 합류 서버로 설정할 것이기에 S1에서 구문을 실행합니다.
만일 group_replication_single_primary_mode=ON 일 경우 싱글 프라이머리 모드이므로 S1이 자동으로 프라이머리 서버가 됩니다. group_replication_single_primary_mode=OFF 일 경우 멀티 프라이머리 모드이므로 모든 서버가 프라이머리가 되므로 S1인스턴스는 이후 합류할 S2, S3와 역할이 크게 다르지 않습니다.
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
또는 MySQL 8.0.21 이상에서 START GROUP_REPLICATION 문에서 접속정보를 설정하는 기능이 추가되었습니다.
START GROUP_REPLICATION 문에서 접속정보를 제공하려면 다음 명령을 실행하면 됩니다.
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION USER='rpl_user', PASSWORD='password';
SET GLOBAL group_replication_bootstrap_group=OFF;
※ 주의
START GROUP_REPLICATION 문에서 지정된 사용자 자격 증명은 메모리에만 저장되며, STOP GROUP_REPLICATION
문을 실행하거나 서버를 종료하면 제거됩니다.
따라서 그룹 복제를 자동으로 시작할 때 이러한 자격 증명을 사용할 수 없으며, 자격 증명을 다시 제공하려면 START GROUP_REPLICATION 문을 다시 실행해야 합니다.
이러한 방식으로 사용자 자격 증명을 지정하면 그룹 복제 서버가 무단 접근으로부터 보호될 수 있습니다.
START GROUP_REPLICATION 문이 실행된 후 그룹이 생성됩니다.
그룹이 정상적으로 생성되었는지는 아래 쿼리를 실행하여 확인할 수 있습니다.
SELECT * FROM performance_schema.replication_group_members;
위 결과는 그룹에 1b5a9e30-f8c0-11ef-9923-525400f2cf32 고유 식별자를 가진 멤버가 존재하며, 현재 ONLINE 상태이며 3306포트로 클라이언트 연결을 수락하고 있음을 알려줍니다.
실제로 서버가 그룹 내에 있으며 동기화가 가능한 상태인지 확인하기 위해 테이블을 생성하고 데이터를 추가해봅니다.
-- 데이터베이스/테이블 생성 및 데이터 추가
CREATE DATABASE test;
USE test;
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
INSERT INTO t1 VALUES (1, 'Luis');
-- 결과 확인
SHOW DATABASES LIKE 'test';
+-----------------+
| Database (test) |
+-----------------+
| test |
+-----------------+
SELECT * FROM test.t1;
+----+------+
| c1 | c2 |
+----+------+
| 1 | Luis |
+----+------+
SHOW BINLOG EVENTS;
6. 그룹에 인스턴스 추가하기
S1(192.168.1.11)에서 그룹 부트스트랩이 완료되었다면 S2(192.168.1.12), S3(192.168.1.13)을 그룹에 추가해야 합니다.
my.cnf 의 그룹복제 설정은 server_id, plugin_replication_local_address 외에는 S1과 다른 설정값이 없어야 합니다.
S2와 S3에서 아래 쿼리를 실행하여 그룹 복제 계정을 등록합니다.
-- MySQL 8.0.23 이전 버전
CHANGE MASTER TO
MASTER_USER='rpl_user',
MASTER_PASSWORD='password'
FOR CHANNEL 'group_replication_recovery';
-- MySQL 8.0.23 이상 버전
CHANGE REPLICATION SOURCE TO
SOURCE_USER='rpl_user',
SOURCE_PASSWORD='password'
FOR CHANNEL 'group_replication_recovery';
이후 START GROUP_REPLICATION문을 통해 그룹에 인스턴스를 합류시킵니다.
START GROUP_REPLICATION;
그룹을 부트스트랩 할 때와 마찬가지로 START GROUP_REPLICATION 문에 계정 정보를 추가하여 합류할 수도 있습니다.
여기서 설정된 계정 정보는 서버 재시작 및 그룹 복제 중단 시 제거됩니다.
그룹에 정상적으로 합류되었는지는 performance_schema.replication_group_members 테이블에서 확인할 수 있습니다.
SELECT * FROM performance_schema.replication_group_members;
S2와 S3가 그룹에 합류하려고 할 때, 분산 복구 매커니즘으로 S2와 S3는 S1과 동일한 트랜잭션을 적용하게 됩니다.
이 프로세스가 완료되어야 멤버로 합류할 수 있으며, 이 시점에서 performance_schema.replication_group_members의 MEBER_STATE컬럼이 ONLINE 상태로 표시됩니다.
ONLINE 상태가 되면 그룹과 함께 트랜잭션을 처리하기 시작합니다.
S2와 S3가 실제로 S1과 동기화되었는지는 그룹 부트스트랩 후 S1에 발생한 변경 사항이 S2와 S3에 적용되었는지를 확인하여 알 수 있습니다.
-- 부트스트랩 후 S1에 적용한 변경사항이 S2와 S3에서도 발생하였는지 확인
SHOW DATABASES LIKE 'test';
+-----------------+
| Database (test) |
+-----------------+
| test |
+-----------------+
SELECT * FROM test.t1;
+----+------+
| c1 | c2 |
+----+------+
| 1 | Luis |
+----+------+
SHOW BINLOG EVENTS;
7. 구성 중 발생 가능한 에러
1) [ERROR] Unknown MySQL server host [MY-010584],[MY-002005]
[ERROR] [MY-010584] [Repl] Slave I/O for channel 'group_replication_recovery': error connecting to master 'rpl_user@S1-192-168-1-11:3306' - retry-time: 60 retries: 1 message: Unknown MySQL server host 'S1-192-168-1-11' (-3), Error_code: MY-002005
위 에러는 DNS 설정이 올바르게 되어있지 않거나, 해당 호스트명이 서버에서 인식되지 않는 경우 발생합니다.
ping hostname
nslookup hostname
getent hosts
S2(192.168.1.12) 기준 S1과 S3의 IP와 호스트명을 /etc/hosts에 추가하여 해결할 수 있습니다.
# /etc/hosts에 아래 내용 추가
192.168.1.11 S1-192-168-1-11
192.168.1.13 S3-192-168-1-13
2) [ERROR] The member contains transactions not present in the group [MY-011526]
[ERROR] [MY-011526] [Repl] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-3 > Group transactions: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1'
[ERROR] [MY-011522] [Repl] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'
위 에러는 해당 멤버가 그룹보다 더 많은 트랜잭션을 가지고 있어 그룹에 합류하지 못해 발생합니다.
그룹 내 멤버와 데이터가 동일할 경우, 아래와 같이 에러가 발생한 멤버의 트랜잭션 기록을 초기화 하여 해결할 수 있습니다.
-- 각 멤버의 GTID 확인
SHOW VARIABLES LIKE 'gtid_executed';
-- 에러가 발생한 멤버에서 쿼리 실행
RESET MASTER;
'Database > MySQL' 카테고리의 다른 글
[MySQL] InnoDB Cluster 3부작 : 3. MySQL InnoDB Cluster Metadata 생성 및 MySQL Router 구성하기 (0) | 2025.04.01 |
---|---|
[MySQL] InnoDB Adaptive 시스템 변수 (0) | 2025.03.27 |
[MySQL] InnoDB Cluster 3부작 : 1. Group Replication (1) - 개념 이해하기 (0) | 2025.03.17 |
[MySQL] binlog_format (0) | 2025.03.12 |
[MySQL] innodb_flush_method (O_DIRECT, O_DSYNC, fsync) (0) | 2025.03.11 |