MySQL Group Replication 개념 및 원리 가이드

MySQL Group Replication 개념 및 원리 가이드

소개

이 가이드는 MySQL Group Replication의 핵심 개념, 동작 원리, 그리고 기존 복제 기술과의 차이점을 체계적으로 설명합니다. 파트너사 기술 담당자가 Group Replication 도입을 검토하거나 운영 시 필요한 이론적 배경을 제공합니다.

대상 독자: MySQL 기본 지식을 보유한 DBA 및 시스템 엔지니어
예상 학습 시간: 30-45분
목적: Group Replication의 이해를 통한 올바른 설계 및 운영 방향성 제시

사전 지식

필요한 기본 개념

  • MySQL 복제(Replication) 기본 이해

  • GTID(Global Transaction Identifier) 개념

  • InnoDB 스토리지 엔진 이해

  • 트랜잭션 및 ACID 속성


Group Replication이란?

정의

MySQL Group Replication은 MySQL 5.7부터 도입된 네이티브 고가용성 솔루션으로, 여러 MySQL 서버가 하나의 그룹을 형성하여 동기식 복제를 통해 데이터 일관성을 보장하는 기술입니다.

핵심 특징

특징

설명

특징

설명

동기식 복제

트랜잭션이 과반수 노드에서 승인된 후 커밋

자동 페일오버

Primary 노드 장애 시 자동으로 새 Primary 선출

충돌 감지

동시 트랜잭션 간 충돌 자동 감지 및 해결

멤버십 관리

노드 추가/제거 자동 처리

내장 솔루션

별도 외부 도구 없이 MySQL 자체 기능으로 구현


기존 복제 방식과의 차이점

MySQL에는 여러 복제 방식이 있으며, 각각의 동작 원리와 특징이 다릅니다. Group Replication을 이해하기 위해서는 기존 방식들과의 차이점을 명확히 아는 것이 중요합니다.

1. 전통적인 비동기 복제 (Asynchronous Replication)

아키텍처

Master ────→ Slave 1 └───→ Slave 2 └───→ Slave 3

동작 과정

-- 1. Master에서 트랜잭션 실행 BEGIN; INSERT INTO users (name) VALUES ('Alice'); COMMIT; -- ← Master에서 즉시 커밋 완료 -- 2. Binary Log에 기록 -- 3. Slave들이 각자 타이밍에 가져와서 적용

상세 동작 순서:

1. 클라이언트 → Master: "INSERT 실행해줘" 2. Master: 트랜잭션 실행 및 즉시 커밋 3. Master: Binary Log에 변경사항 기록 4. Master → 클라이언트: "완료했어!" (응답) 5. Slave들: 각자 타이밍에 Binary Log 읽어서 적용

특징:

  • 빠른 응답: Master에서 즉시 커밋, 응답 속도 빠름

  • 네트워크 독립적: Slave 장애가 Master에 영향 없음

  • 데이터 불일치: Slave에 적용되기 전에 Master 장애 시 데이터 손실

  • 복제 지연: 네트워크나 부하로 인한 지연 발생

실제 예시:

-- Master에서 실행 INSERT INTO orders (user_id, amount) VALUES (123, 50000); -- → 즉시 "성공!" 응답 -- 하지만 Slave는 1초 후에 복제됨 -- 이 1초 동안 Slave에서 조회하면 데이터 없음!

2. 반동기 복제 (Semi-synchronous Replication)

동작 과정

-- 1. Master에서 트랜잭션 실행 BEGIN; INSERT INTO users (name) VALUES ('Bob'); COMMIT; -- ← 최소 1개 Slave 확인 후 커밋

상세 동작 순서:

1. 클라이언트 → Master: "INSERT 실행해줘" 2. Master: 트랜잭션 실행 (아직 커밋 안함) 3. Master → Slave들: "이 변경사항 받았어?" 4. Slave (최소 1개): "받았어!" (ACK 응답) 5. Master: 이제 커밋 완료 6. Master → 클라이언트: "완료했어!"

특징:

  • 데이터 안정성: 최소 1개 Slave에는 보장

  • 손실 위험 감소: Master 장애 시에도 Slave에 데이터 존재

  • 성능 저하: Slave 응답까지 기다려야 함

  • 수동 페일오버: 여전히 Master 장애 시 수동 전환 필요

타임아웃 설정:

-- Slave 응답을 10초까지 기다림 SET GLOBAL rpl_semi_sync_master_timeout = 10000; -- 타임아웃 시 비동기 모드로 전환

3. Group Replication (동기식 복제)

아키텍처

┌─── Node 1 (Primary) ───┐ │ │ Node 3 ←── Group ──→ Node 2 │ (Consensus) │ └────────────────────────┘

동작 과정

-- Primary에서 트랜잭션 실행 BEGIN; INSERT INTO users (name) VALUES ('Charlie'); COMMIT; -- ← 과반수 노드 승인 후 커밋

상세 동작 순서:

1. 클라이언트 → Primary: "INSERT 실행해줘" 2. Primary: 트랜잭션 실행 (아직 커밋 안함) 3. Primary → 모든 노드: "이 변경사항 어때?" 4. 모든 노드: Certification (충돌 검사) 수행 5. 각 노드 → Primary: "승인!" 또는 "거부!" 6. Primary: 과반수 승인 시 커밋, 아니면 롤백 7. Primary → 클라이언트: "완료!" 또는 "실패!" 8. 모든 노드: 동일한 결과 적용

특징:

  • 강한 일관성: 모든 노드에서 동일한 데이터 보장

  • 자동 페일오버: Primary 장애 시 자동 전환 (30초~1분)

  • 충돌 감지: 동시 트랜잭션 충돌 자동 해결

  • 성능 오버헤드: 합의 과정으로 인한 지연 (10-30%)

4. 상세 비교 분석

데이터 일관성 시나리오

상황: Primary/Master에서 데이터 삽입 후 즉시 장애 발생

비동기 복제
-- Master에서 INSERT INTO accounts (id, balance) VALUES (1, 100000); -- "성공!" 응답 후 Master 즉시 장애 -- Slave 상태: 아직 복제 안됨 → 데이터 손실! -- 복구 후: 해당 거래 기록 사라짐
반동기 복제
-- Master에서 INSERT INTO accounts (id, balance) VALUES (1, 100000); -- Slave 확인 후 "성공!" 응답, 그 후 Master 장애 -- Slave 상태: 데이터 있음 → 손실 없음! -- 하지만 수동으로 Slave를 Master로 승격 필요
Group Replication
-- Primary에서 INSERT INTO accounts (id, balance) VALUES (1, 100000); -- 과반수 승인 후 "성공!" 응답, 그 후 Primary 장애 -- 다른 노드들: 모두 동일한 데이터 가짐 -- 자동으로 새 Primary 선출 (30초~1분) -- 서비스 자동 복구

성능 비교

-- 동일한 INSERT 작업 시간 비교 (3개 노드 기준) -- 비동기 복제 INSERT INTO test VALUES (1, 'data'); -- 5ms -- 반동기 복제 INSERT INTO test VALUES (1, 'data'); -- 15ms (네트워크 지연) -- Group Replication INSERT INTO test VALUES (1, 'data'); -- 25ms (합의 과정)

읽기 일관성 비교

비동기 복제
-- Master에서 UPDATE accounts SET balance = 50000 WHERE id = 1; -- 즉시 Slave에서 조회 SELECT balance FROM accounts WHERE id = 1; -- 결과: 100000 (아직 구 데이터!) → Read-after-Write 문제
Group Replication
-- Primary에서 UPDATE accounts SET balance = 50000 WHERE id = 1; -- 즉시 Secondary에서 조회 SELECT balance FROM accounts WHERE id = 1; -- 결과: 50000 (최신 데이터 보장!)

5. 장애 상황별 대응

Master/Primary 장애 시나리오

전통적인 복제
1. Master 장애 감지 (수동 또는 모니터링 시스템) 2. 관리자 개입 필요 3. Slave 중 하나를 Master로 수동 승격 4. 애플리케이션 연결 정보 변경 5. 서비스 복구 소요 시간: 10분~수 시간 (수동 작업)
Group Replication
1. Primary 장애 자동 감지 (수초) 2. 남은 노드들이 자동으로 새 Primary 선출 3. 클라이언트 재연결 시 자동으로 새 Primary 연결 4. 서비스 자동 복구 소요 시간: 30초~1분 (자동 처리)

네트워크 분할 (Split-brain) 시나리오

전통적인 복제
Scenario: Master와 Slave 간 네트워크 단절 Master: 계속 쓰기 허용 Slave: 독립적으로 동작 가능 (위험!) 결과: 두 곳에서 서로 다른 데이터 생성 → 심각한 데이터 불일치
Group Replication
Scenario: 네트워크 분할로 노드들이 분리 Group A (2개 노드): 과반수 ✅ → 정상 동작 (쓰기 가능) Group B (1개 노드): 과반수 미달 ❌ → 읽기 전용 결과: - Group A에서 서비스 계속 제공 - 데이터 일관성 보장 (Group B는 쓰기 불가) - 네트워크 복구 후: 자동으로 정상 상태 복구

Primary 선출 규칙:

  • Primary가 과반수 그룹에 포함: 기존 Primary 유지

  • Primary가 소수 그룹에 포함: 과반수 그룹에서 새 Primary 선출

구체적 시나리오:

초기: 1번(Primary), 2번(Secondary), 3번(Secondary) Case 1: 1번 | 2,3번 분할 → 2,3번 그룹에서 새 Primary 선출 (1번은 읽기 전용) Case 2: 1,2번 | 3번 분할 → 1번이 Primary 유지 (3번은 읽기 전용)

6. 운영 복잡도 비교

일상 운영 작업

전통적인 복제
# Slave 추가 시 1. Master에서 백업 생성 2. 새 Slave 서버에 복원 3. Slave 복제 설정 4. 복제 시작 및 확인 5. 애플리케이션 읽기 분산 설정 # 관리 포인트: 5-10개
Group Replication
# 새 노드 추가 시 1. 새 노드에 Group Replication 설정 2. START GROUP_REPLICATION 실행 3. 자동으로 데이터 동기화 및 참여 # 관리 포인트: 2-3개

모니터링 복잡도

전통적인 복제
-- 각 Slave별로 확인 필요 SHOW SLAVE STATUS\G -- Slave 1에서 SHOW SLAVE STATUS\G -- Slave 2에서 SHOW SLAVE STATUS\G -- Slave 3에서 -- 확인 항목: Seconds_Behind_Master, Last_Error, etc.
Group Replication
-- 어떤 노드에서든 전체 상태 확인 가능 SELECT * FROM performance_schema.replication_group_members; -- 모든 노드의 상태를 한 번에 확인

7. 사용 사례별 권장사항

비동기 복제가 적합한 경우

✅ 높은 쓰기 성능이 중요 ✅ 약간의 데이터 손실 허용 가능 ✅ 지리적으로 멀리 분산된 환경 ✅ 네트워크 지연이 큰 환경 예시: 로그 수집 시스템, 분석용 데이터 복제

반동기 복제가 적합한 경우

✅ 데이터 손실은 최소화하고 싶지만 ✅ 자동 페일오버는 필요 없음 ✅ 기존 인프라 유지하면서 안정성 향상 예시: 중요도 중간인 비즈니스 시스템

Group Replication이 적합한 경우

✅ 데이터 일관성이 매우 중요 ✅ 자동 페일오버 필요 ✅ 운영 복잡도 최소화 원함 ✅ 동일 리전/데이터센터 환경 예시: 금융 시스템, 전자상거래, 핵심 비즈니스 DB

아키텍처 및 동작 원리

1. Group Communication System (GCS)

Group Replication의 핵심은 Paxos 합의 알고리즘 기반의 통신 시스템입니다.

Application Layer MySQL Server Group Replication Plugin Group Communication System (Paxos) Network Layer

2. 트랜잭션 처리 과정

Step 1: 트랜잭션 실행

-- Primary 노드에서 BEGIN; INSERT INTO users (name) VALUES ('Alice'); COMMIT; -- 여기서 Group Replication 동작 시작

Step 2: Certification 과정

1. Primary에서 트랜잭션 생성 2. 모든 노드로 트랜잭션 전송 3. 각 노드에서 충돌 검사 (Certification) 4. 과반수 승인 시 커밋 5. 모든 노드에 적용

Step 3: Write-set 생성

Write-set = { "database": "testdb", "table": "users", "primary_key": "123", "operation": "INSERT", "gtid": "uuid:transaction_id" }

3. 충돌 감지 메커니즘

동시 트랜잭션 시나리오:

-- Node A에서 동시에 UPDATE users SET balance = 1000 WHERE id = 123; -- Node B에서 동시에 UPDATE users SET balance = 1500 WHERE id = 123;

충돌 해결:

  1. 두 트랜잭션이 동일한 Primary Key에 접근

  2. Group Replication이 충돌 감지

  3. 먼저 도착한 트랜잭션 승인

  4. 나중 트랜잭션은 롤백 및 재시도


Single Primary vs Multi Primary 모드

Single Primary 모드 (권장)

Primary (읽기/쓰기) ──┐ Secondary (읽기만) ──┼─── Group Secondary (읽기만) ──┘

특징:

  • 하나의 Primary: 모든 쓰기는 Primary에서만

  • 여러 Secondary: 읽기 전용으로 동작

  • 자동 Primary 선출: 장애 시 Secondary 중 하나가 Primary로 승격

장점:

  • ✅ 충돌 최소화

  • ✅ 관리 단순성

  • ✅ 일관성 보장

사용 사례:

  • 일반적인 웹 애플리케이션

  • 읽기 확장이 주요 목적

  • 데이터 일관성이 중요한 시스템

Multi Primary 모드

Primary (읽기/쓰기) ──┐ Primary (읽기/쓰기) ──┼─── Group Primary (읽기/쓰기) ──┘

특징:

  • 모든 노드가 Primary: 모든 노드에서 읽기/쓰기 가능

  • 동시 쓰기: 여러 노드에서 동시 쓰기 지원

  • 충돌 관리: 더 복잡한 충돌 감지 및 해결

장점:

  • ✅ 쓰기 성능 향상

  • ✅ 지리적 분산 환경에 적합

  • ✅ 로드 분산 효과

단점:

  • ❌ 충돌 가능성 증가

  • ❌ 관리 복잡도 상승

  • ❌ 특정 제약사항 추가

사용 사례:

  • 지리적으로 분산된 애플리케이션

  • 높은 쓰기 성능이 필요한 경우

  • 네트워크 분할에 대한 내성이 필요한 경우


제약사항과 한계

1. 테이블 제약사항

Primary Key 필수

-- ❌ 허용되지 않음 CREATE TABLE users ( name VARCHAR(50), email VARCHAR(100) ); -- ✅ 올바른 방법 CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), email VARCHAR(100) );

스토리지 엔진 제한

-- ❌ 허용되지 않음 CREATE TABLE logs ( id INT PRIMARY KEY, message TEXT ) ENGINE=MyISAM; -- ✅ 올바른 방법 CREATE TABLE logs ( id INT PRIMARY KEY, message TEXT ) ENGINE=InnoDB;

2. Foreign Key 제약

-- ❌ 제한됨 CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); -- ✅ 권장 방법 CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) -- CASCADE 옵션 사용하지 않음 );

3. 트랜잭션 크기 제한

-- 기본 제한: 150MB SHOW VARIABLES LIKE 'group_replication_transaction_size_limit'; -- 대용량 트랜잭션은 분할 처리 필요 -- ❌ 한 번에 처리 INSERT INTO large_table SELECT * FROM huge_dataset; -- ✅ 배치 처리 INSERT INTO large_table SELECT * FROM huge_dataset LIMIT 10000; -- 여러 번 반복

4. 지원되지 않는 SQL 문

-- ❌ 제한됨 CREATE TABLE temp AS SELECT * FROM users; SELECT * INTO OUTFILE '/tmp/data.txt' FROM users; LOAD DATA INFILE '/tmp/data.txt' INTO TABLE users; -- ✅ 대안 CREATE TABLE temp LIKE users; INSERT INTO temp SELECT * FROM users;

장단점 분석

장점

영역

장점

설명

영역

장점

설명

가용성

자동 페일오버

Primary 장애 시 자동 복구 (30초~1분)

일관성

강한 데이터 일관성

모든 노드에서 동일한 데이터 보장

확장성

읽기 확장성

Secondary 노드로 읽기 부하 분산

관리

운영 단순화

외부 도구 없이 MySQL 자체 기능

투명성

애플리케이션 투명성

기존 애플리케이션 코드 변경 최소화

단점

영역

단점

설명

영역

단점

설명

성능

쓰기 성능 오버헤드

동기식 복제로 인한 지연 (10-30% 감소)

제약

스키마 제약사항

Primary Key 필수, Foreign Key 제한

복잡성

네트워크 의존성

안정적인 네트워크 환경 필요

확장

노드 수 제한

실용적 한계 9개 노드 (홀수 권장)

지연

네트워크 지연 민감

지리적 분산 시 성능 저하


사용 사례

1. 적합한 사용 사례

웹 애플리케이션

특징: 읽기 중심, 높은 가용성 요구 구성: Single Primary 모드 노드: 3-5개 노드 (동일 리전)

전자상거래 플랫폼

특징: 트랜잭션 일관성 중요 구성: Single Primary 모드 노드: 3개 노드 (다중 AZ)

SaaS 서비스

특징: 다중 테넌트, 자동 복구 필요 구성: Single Primary 모드 노드: 5개 노드 (지역별 분산)

2. 부적합한 사용 사례

대용량 배치 처리

문제: 트랜잭션 크기 제한 대안: 전통적인 Master-Slave 복제

실시간 분석 시스템

문제: 쓰기 성능 오버헤드 대안: 전용 분석 DB (ClickHouse, BigQuery)

IoT 센서 데이터

문제: 높은 쓰기 빈도, 큰 데이터량 대안: 시계열 DB (InfluxDB, TimescaleDB)

성능 고려사항

1. 네트워크 요구사항

지연시간: < 5ms (동일 리전 권장) 대역폭: 충분한 대역폭 (복제 트래픽 고려) 안정성: 99.9% 이상 네트워크 가용성

2. 하드웨어 권장사항

CPU: 8 Core 이상 (합의 알고리즘 연산) Memory: 16GB 이상 (InnoDB Buffer Pool) Storage: SSD 권장 (빠른 I/O) Network: 10Gbps 이상 (고속 복제)

3. 성능 튜닝 파라미터

-- Group Replication 최적화 SET GLOBAL group_replication_compression_threshold = 1000000; SET GLOBAL group_replication_recovery_get_public_key = ON; SET GLOBAL group_replication_poll_spin_loops = 1000; -- InnoDB 최적화 SET GLOBAL innodb_buffer_pool_size = '12G'; SET GLOBAL innodb_log_file_size = '2G'; SET GLOBAL innodb_flush_log_at_trx_commit = 1;

AWS Aurora MySQL vs Group Replication 비교

많은 개발자들이 "AWS Aurora MySQL에서는 Primary Key 없어도 되는데, 왜 Group Replication에서는 필수인가?"라고 궁금해합니다. 이는 근본적인 아키텍처 차이 때문입니다.

1. 복제 방식의 차이

AWS Aurora MySQL

Application Aurora MySQL Engine Aurora Storage (클러스터 스토리지) 6개 복사본 (3개 AZ, 각각 2개씩)

특징:

  • 스토리지 레벨 복제: 데이터베이스 엔진 아래에서 복제

  • 페이지 단위 복제: 변경된 데이터 페이지 전체를 복제

  • Row 식별 불필요: 페이지 전체를 복사하므로 개별 행 식별 필요 없음

Group Replication

Application MySQL Engine Binary Log (Row 변경사항) Group Replication (행 단위 복제) 다른 노드들

특징:

  • 바이너리 로그 기반: 변경된 행(Row)의 정보만 전송

  • 행 단위 복제: 개별 행의 변경사항을 복제

  • Row 식별 필수: 어떤 행이 변경되었는지 정확히 식별해야 함

2. Primary Key가 필요한 이유

Aurora의 경우

-- Primary Key 없는 테이블 CREATE TABLE users (name VARCHAR(50), email VARCHAR(100)); INSERT INTO users VALUES ('John', 'john@example.com'); UPDATE users SET email = 'new@example.com' WHERE name = 'John';

Aurora 복제 과정:

1. 변경된 데이터 페이지 전체를 스토리지에서 복제 2. 페이지 내 모든 정보가 그대로 전송됨 3. Primary Key 없어도 문제없음 (페이지 전체 복사)

Group Replication의 경우

-- 같은 테이블, 같은 작업 UPDATE users SET email = 'new@example.com' WHERE name = 'John';

Group Replication 복제 과정:

1. 바이너리 로그에 변경사항 기록 2. "name='John'인 행을 찾아서 email 변경" 정보 전송 3. 다른 노드에서 동일한 행을 찾아야 함 4. Primary Key 없으면 어떤 행인지 특정 불가능!

3. 문제 상황 시뮬레이션

Primary Key 없을 때 발생하는 문제

-- 문제 상황: 동일한 데이터를 가진 여러 행 CREATE TABLE logs (level VARCHAR(10), message TEXT); INSERT INTO logs VALUES ('ERROR', 'Database connection failed'); INSERT INTO logs VALUES ('ERROR', 'Database connection failed'); -- 동일한 데이터 INSERT INTO logs VALUES ('ERROR', 'Database connection failed'); -- 동일한 데이터 -- 이제 하나만 업데이트하려고 함 UPDATE logs SET message = 'Database connection failed - RESOLVED' WHERE level = 'ERROR' LIMIT 1;

Group Replication에서 복제 시:

Node A: 첫 번째 ERROR 행 업데이트 Node B: 어떤 ERROR 행을 업데이트해야 할지 모름! → 첫 번째? 두 번째? 세 번째? → 데이터 불일치 발생!

Aurora에서는:

스토리지 레벨에서 정확한 페이지가 복제되므로 문제없음

4. Write-set 생성 방식 차이

Group Replication의 Write-set

{ "database": "testdb", "table": "users", "primary_key": "id=123", // Primary Key로 행 식별 "before": {"name": "John", "email": "old@example.com"}, "after": {"name": "John", "email": "new@example.com"} }

Primary Key 없으면:

{ "database": "testdb", "table": "users", "primary_key": "???", // 행을 식별할 방법이 없음! "before": {"name": "John", "email": "old@example.com"}, "after": {"name": "John", "email": "new@example.com"} }

5. 충돌 감지 메커니즘 차이

Aurora MySQL

  • 스토리지 레벨 잠금: 페이지 단위로 잠금 관리

  • 복제 충돌 없음: 스토리지에서 자동 처리

Group Replication

-- 동시 트랜잭션 시나리오 -- Node A에서 UPDATE users SET balance = 1000 WHERE id = 123; -- Primary Key 사용 -- Node B에서 동시에 UPDATE users SET balance = 1500 WHERE id = 123; -- 같은 Primary Key

충돌 감지:

Group Replication: "id=123에 대한 충돌 감지!" → 하나만 승인 Primary Key 없으면: "어떤 행에 대한 충돌인지 모름!" → 감지 불가

실제 사용 시 고려사항

1. Aurora를 Group Replication으로 마이그레이션 시

주의사항:

-- Aurora에서 잘 동작하던 테이블 CREATE TABLE session_logs ( timestamp DATETIME, user_agent TEXT, ip_address VARCHAR(45) ); -- Group Replication에서는 에러! -- 해결방법: Primary Key 추가 ALTER TABLE session_logs ADD COLUMN id BIGINT PRIMARY KEY AUTO_INCREMENT FIRST;

2. 각 솔루션의 장단점

항목

AWS Aurora MySQL

Group Replication

항목

AWS Aurora MySQL

Group Replication

Primary Key 요구

선택사항

필수

마이그레이션

쉬움

Primary Key 추가 필요

복제 오버헤드

낮음 (스토리지 레벨)

중간 (바이너리 로그)

벤더 종속성

AWS 종속적

어디서나 사용 가능

비용

높음 (Aurora 프리미엄)

낮음 (일반 EC2)

자동 백업

완전 관리형

수동 구성 필요

3. 언제 무엇을 선택할까?

Aurora MySQL을 선택하는 경우

  • 완전 관리형이 필요한 경우

  • Primary Key 추가가 어려운 레거시 시스템

  • AWS 생태계에 깊이 통합된 환경

  • 운영 리소스가 부족한 경우

Group Replication을 선택하는 경우

  • 비용 최적화가 중요한 경우

  • 멀티 클라우드 또는 온프레미스 환경

  • 세밀한 제어가 필요한 경우

  • 기술적 학습이 목적인 경우


기술적 제약사항 심화 분석

1. 왜 InnoDB만 지원하는가?

Group Replication 요구사항

-- ✅ InnoDB: 트랜잭션 지원, Row-level 잠금 CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50)) ENGINE=InnoDB; -- ❌ MyISAM: 트랜잭션 미지원, Table-level 잠금 CREATE TABLE logs (id INT PRIMARY KEY, message TEXT) ENGINE=MyISAM;

이유:

  • 트랜잭션 지원: ACID 속성 보장 필요

  • Row-level 잠금: 동시성 처리 필요

  • Crash Recovery: 장애 시 일관성 복구 필요

2. Foreign Key CASCADE 제한

-- ❌ 문제가 되는 설정 CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); -- 사용자 삭제 시 DELETE FROM users WHERE id = 123; -- → 연쇄적으로 orders 테이블의 여러 행 삭제 -- → 복잡한 Write-set 생성으로 충돌 가능성 증가

권장 방법:

-- ✅ 애플리케이션에서 관리 CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) -- CASCADE 없음 ); -- 애플리케이션 코드에서 DELETE FROM orders WHERE user_id = 123; -- 먼저 삭제 DELETE FROM users WHERE id = 123; -- 그 다음 삭제

3. 트랜잭션 크기 제한의 배경

-- 기본 제한: 150MB SHOW VARIABLES LIKE 'group_replication_transaction_size_limit';

제한 이유:

  • 메모리 사용: 모든 노드가 트랜잭션을 메모리에 보관

  • 네트워크 전송: 대용량 데이터 전송 시 네트워크 부하

  • Certification 시간: 큰 트랜잭션일수록 검증 시간 증가

해결 방법:

-- ❌ 한 번에 대량 처리 INSERT INTO large_table SELECT * FROM source_table; -- 1GB 데이터 -- ✅ 배치 처리 INSERT INTO large_table SELECT * FROM source_table LIMIT 10000; -- 10MB씩 나누어 처리

참고 자료