
MySQL에서 제공하는 고가용성(HA) 솔루션으로, 다음 구성요소들을 조합하여 클러스터를 구성합니다:
MySQL Clone 기능으로 신규 인스턴스 자동 동기화
mysql/
├── docker-compose.yml
├── mysql-shell/
│ ├── Dockerfile/
│ └── run.sh
├── scripts/
│ ├── db.sql
│ └── setupCluster.js
├── server-1/
├── server-2/
├── server-3/
├── mysql-router.env
├── mysql-server.env
└── mysql.shell.env
다음은 MySQL InnoDB Cluster를 Docker Compose로 구성한 예시입니다. 이 구성은 3개의 MySQL 서버를 설정하고, 각 서버는 동일한 클러스터에 속하게 됩니다.
services:
mysql-server-1:
container_name: mysql-server-1
image: mysql/mysql-server:8.0.12
env_file:
- mysql-server.env
ports:
- "3301:3306"
volumes:
- ./server-1/data:/var/lib/mysql
networks:
- eventor_back-network
environment:
TZ: Asia/Seoul
mysql-server-2:
container_name: mysql-server-2
image: mysql/mysql-server:8.0.12
env_file:
- mysql-server.env
ports:
- "3302:3306"
volumes:
- ./server-2/data:/var/lib/mysql
networks:
- eventor_back-network
environment:
TZ: Asia/Seoul
mysql-server-3:
container_name: mysql-server-3
image: mysql/mysql-server:8.0.12
env_file:
- mysql-server.env
ports:
- "3303:3306"
volumes:
- ./server-3/data:/var/lib/mysql
networks:
- eventor_back-network
environment:
TZ: Asia/Seoul
mysql-shell:
container_name: mysql-shell
env_file:
- mysql-shell.env
build:
context: .
dockerfile: ./mysql-shell/Dockerfile
command: /run.sh
volumes:
- ./scripts/:/scripts/
depends_on:
- mysql-server-1
- mysql-server-2
- mysql-server-3
networks:
- eventor_back-network
mysql-router:
container_name: mysql-router
env_file:
- mysql-router.env
image: mysql/mysql-router:8.0
ports:
- "6446:6446"
- "6447:6447"
depends_on:
- mysql-server-1
- mysql-server-2
- mysql-server-3
- mysql-shell
restart: on-failure
networks:
- eventor_back-network
networks:
eventor_back-network:
external: true
[mysqld]
server_id=1
report_host=mysql-server-1
relay_log=relay-bin
relay_log_index=relay-bin.index
binlog_checksum=NONE
gtid_mode=ON
enforce_gtid_consistency=ON
log_bin=ON
log_slave_updates=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
transaction_write_set_extraction=XXHASH64
user=mysql
skip-host-cache
default_authentication_plugin=mysql_native_password
binlog_transaction_dependency_tracking=WRITESET
default-time-zone = '+09:00'
server_id: 각 인스턴스의 고유 ID. 반드시 서로 달라야 합니다. 예: mysql-server-2는 server_id=2.report_host: 인스턴스 식별용 호스트명. docker-compose 내 컨테이너 이름과 맞추는 것이 좋습니다.gtid_mode, enforce_gtid_consistency: GTID 기반 복제를 위한 필수 옵션.log_bin, log_slave_updates: binary log 활성화 및 복제 로그 유지.transaction_write_set_extraction: Group Replication을 위한 트랜잭션 추적 방식.binlog_transaction_dependency_tracking=WRITESET: 충돌 최소화를 위한 의존성 추적 방식.default_authentication_plugin: 기본 인증 플러그인을 mysql_native_password로 고정 (MySQL 8.x 이상 호환 이슈 방지용).docker-compose up -d
docker exec -it mysql-server-1 bash
mysqlsh root@mysql-server-1:3306
mysqlsh는 MySQL 8에서 클러스터 및 고가용성 관련 기능을 지원하는 셸입니다.mysql-server-1에 접속한 후, JavaScript 모드에서 클러스터 명령을 실행합니다.dba.upgradeMetadata()
dba.getCluster().rescan()
WARNING: The Cluster is not configured to use 'group_replication_view_change_uuid', which is required for InnoDB ClusterSet. Configuring it requires a full Cluster reboot.
Would you like 'group_replication_view_change_uuid' to be configured automatically? [Y/n]: y
group_replication_view_change_uuid 는 ClusterSet 구성 시 필수 옵션입니다.y를 입력하여 자동 설정을 진행합니다.이후 출력:
NOTE: The Cluster's group_replication_view_change_uuid is not set
Generating and setting a value for group_replication_view_change_uuid...
WARNING: The Cluster must be completely taken OFFLINE and restarted (dba.rebootClusterFromCompleteOutage()) for the settings to be effective
Updating group_replication_view_change_uuid in the Cluster's metadata...
Updating group_replication_transaction_size_limit in the Cluster's metadata...
InnoDB Cluster를 사용할 경우, 클러스터 내 장애 조치(Failover)나 자동 복구 기능을 활용하기 위해 MySQL Router를 경유하여 연결해야 합니다.
JDBC URL도 그에 맞게 바꿔야 합니다. 기존에는:
InnoDB Cluster를 구성하기 전, 일반적인 JDBC URL은 다음과 같이 설정되어 있었습니다:
spring.datasource.url=jdbc:mysql://mysql:3306/eventor
여기서 mysql은 Docker Compose 등에서 정의한 MySQL 컨테이너 이름이고, 포트는 기본 포트 3306을 사용합니다.
MySQL Router를 사용하면 다음과 같이 URL이 변경됩니다:
spring.datasource.url=jdbc:mysql://mysql-router:6446/eventor
mysql-router: Docker Compose에서 정의한 MySQL Router 컨테이너 이름6446: MySQL Router의 Read-Write 포트 (기본값)eventor: 접속할 데이터베이스 이름MySQL Router는 내부적으로 클러스터 내에서 쓰기 가능한 Primary 노드로 트래픽을 라우팅해줍니다.
DataSourceConfig.java
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.dbcp2.username}")
private String username;
@Value("${spring.datasource.dbcp2.password}")
private String password;
/**
* PoolSize = Tn × ( Cm - 1 ) + ( Tn / 2 )
* thread count : 12
* simultaneous connection count : 2
* pool size : 12 * ( 2 – 1 ) + (12 / 2) = 18
*/
@Bean
public BasicDataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 최적화 파라미터 설정
dataSource.setInitialSize(18);
dataSource.setMaxTotal(18);
dataSource.setMaxIdle(18);
dataSource.setMinIdle(18);
// 추가 최적화 설정
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery("SELECT 1");
return dataSource;
}
// 이중화
}
MySQL InnoDB Cluster에서 서버가 재부팅된 후, 일부 서버가 RECOVERING 상태로 전환될 수 있습니다. RECOVERING 상태에서 ONLINE 상태로 전환하는 방법에 대해 여러 번 시도했지만, 결국 해결하지 못했습니다.
먼저 docker-compose로 모든 컨테이너를 다시 올려줍니다.
docker-compose up -d
복구의 핵심은 가장 최신 트랜잭션 데이터를 가진 노드를 기준 서버(source) 로 지정하는 것입니다. 각 서버에 접속해 아래 명령어로 GTID 값을 비교하세요:
SHOW GLOBAL VARIABLES LIKE 'gtid_executed';
docker exec -it mysql-server-1 bash
mysql -u root -p
SHOW GLOBAL VARIABLES LIKE 'gtid_executed';
선택된 기준 서버에 접속 후, MySQL Shell을 사용하여 클러스터를 재시작합니다.
docker exec -it mysql-server-1 bash
mysqlsh root@mysql-server-1:3306
MySQL Shell 내에서 다음 명령어를 실행합니다:
dba.rebootClusterFromCompleteOutage('devCluster')
dba.getCluster().status()
status가 "ONLINE"으로 나올 경우 복구가 성공적으로 완료된 것입니다.mysql-server-2:3306 인스턴스가 Group Replication에 참여하려다 실패함
group_replication_applier 채널의 relay log 파일이 손상됨
오류 메시지:
Error reading relay log event for channel 'group_replication_applier': corrupted data in log event
...
Error running query, slave SQL thread aborted.
relay log 손상:
복구 시 잘못된 바이너리 로그 정보:
이전 상태에서 제대로 정리되지 않은 Group Replication 구성:
group_replication_applier 채널이 중간에 비정상 종료된 이력이 있을 수 있음다음은 mysql-server-2:3306을 클러스터에 다시 참여시키기 위한 절차입니다:
STOP SLAVE FOR CHANNEL 'group_replication_applier';
RESET SLAVE ALL FOR CHANNEL 'group_replication_applier';
참고:
RESET SLAVE ALL은 모든 복제 정보와 relay log를 초기화합니다. 재참여 시 새로 동기화를 수행합니다.
START GROUP_REPLICATION;
MySQL Shell(JS 모드)에서 나가려면 다음 명령어를 입력하세요:
\q
또는
\exit
클러스터 복구 후에는 MySQL Router도 재시작하여 새로운 클러스터 상태를 반영하도록 합니다.
docker-compose restart mysql-router