MySQL Group Replication 개념 및 원리 가이드
- 1 소개
- 2 사전 지식
- 2.1 필요한 기본 개념
- 3 Group Replication이란?
- 4 기존 복제 방식과의 차이점
- 4.1 1. 전통적인 비동기 복제 (Asynchronous Replication)
- 4.2 2. 반동기 복제 (Semi-synchronous Replication)
- 4.2.1 동작 과정
- 4.3 3. Group Replication (동기식 복제)
- 4.4 4. 상세 비교 분석
- 4.4.1 데이터 일관성 시나리오
- 4.4.1.1 비동기 복제
- 4.4.1.2 반동기 복제
- 4.4.1.3 Group Replication
- 4.4.2 성능 비교
- 4.4.3 읽기 일관성 비교
- 4.4.3.1 비동기 복제
- 4.4.3.2 Group Replication
- 4.4.1 데이터 일관성 시나리오
- 4.5 5. 장애 상황별 대응
- 4.5.1 Master/Primary 장애 시나리오
- 4.5.1.1 전통적인 복제
- 4.5.1.2 Group Replication
- 4.5.2 네트워크 분할 (Split-brain) 시나리오
- 4.5.2.1 전통적인 복제
- 4.5.2.2 Group Replication
- 4.5.1 Master/Primary 장애 시나리오
- 4.6 6. 운영 복잡도 비교
- 4.6.1 일상 운영 작업
- 4.6.1.1 전통적인 복제
- 4.6.1.2 Group Replication
- 4.6.2 모니터링 복잡도
- 4.6.2.1 전통적인 복제
- 4.6.2.2 Group Replication
- 4.6.1 일상 운영 작업
- 4.7 7. 사용 사례별 권장사항
- 4.7.1 비동기 복제가 적합한 경우
- 4.7.2 반동기 복제가 적합한 경우
- 4.7.3 Group Replication이 적합한 경우
- 5 아키텍처 및 동작 원리
- 5.1 1. Group Communication System (GCS)
- 5.2 2. 트랜잭션 처리 과정
- 5.2.1 Step 1: 트랜잭션 실행
- 5.2.2 Step 2: Certification 과정
- 5.2.3 Step 3: Write-set 생성
- 5.3 3. 충돌 감지 메커니즘
- 6 Single Primary vs Multi Primary 모드
- 7 제약사항과 한계
- 7.1 1. 테이블 제약사항
- 7.1.1 Primary Key 필수
- 7.1.2 스토리지 엔진 제한
- 7.2 2. Foreign Key 제약
- 7.3 3. 트랜잭션 크기 제한
- 7.4 4. 지원되지 않는 SQL 문
- 7.1 1. 테이블 제약사항
- 8 장단점 분석
- 9 사용 사례
- 9.1 1. 적합한 사용 사례
- 9.2 2. 부적합한 사용 사례
- 9.2.1 대용량 배치 처리
- 9.2.2 실시간 분석 시스템
- 9.2.3 IoT 센서 데이터
- 10 성능 고려사항
- 10.1 1. 네트워크 요구사항
- 10.2 2. 하드웨어 권장사항
- 10.3 3. 성능 튜닝 파라미터
- 11 AWS Aurora MySQL vs Group Replication 비교
- 11.1 1. 복제 방식의 차이
- 11.1.1 AWS Aurora MySQL
- 11.1.2 Group Replication
- 11.2 2. Primary Key가 필요한 이유
- 11.2.1 Aurora의 경우
- 11.2.2 Group Replication의 경우
- 11.3 3. 문제 상황 시뮬레이션
- 11.3.1 Primary Key 없을 때 발생하는 문제
- 11.4 4. Write-set 생성 방식 차이
- 11.4.1 Group Replication의 Write-set
- 11.5 5. 충돌 감지 메커니즘 차이
- 11.5.1 Aurora MySQL
- 11.5.2 Group Replication
- 11.1 1. 복제 방식의 차이
- 12 실제 사용 시 고려사항
- 12.1 1. Aurora를 Group Replication으로 마이그레이션 시
- 12.2 2. 각 솔루션의 장단점
- 12.3 3. 언제 무엇을 선택할까?
- 12.3.1 Aurora MySQL을 선택하는 경우
- 12.3.2 Group Replication을 선택하는 경우
- 13 기술적 제약사항 심화 분석
- 13.1 1. 왜 InnoDB만 지원하는가?
- 13.1.1 Group Replication 요구사항
- 13.2 2. Foreign Key CASCADE 제한
- 13.3 3. 트랜잭션 크기 제한의 배경
- 13.1 1. 왜 InnoDB만 지원하는가?
- 14 참고 자료
소개
이 가이드는 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;
충돌 해결:
두 트랜잭션이 동일한 Primary Key에 접근
Group Replication이 충돌 감지
먼저 도착한 트랜잭션 승인
나중 트랜잭션은 롤백 및 재시도
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 |
|---|---|---|
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씩 나누어 처리