---
title: "MySQL Group Replication 개념: quorum, certification, membership"
description: "MySQL Group Replication의 과반수 합의, 트랜잭션 충돌 인증, 멤버십 변경을 연결해 이해하고 운영 진단과 장애 대응 기준을 정리한다."
tags: [ MySQL, 복제, 고가용성, 트랜잭션, 운영 ]
image: "mysql-report-bg.png"
published: "2026-10-29"
updated: "2026-10-29"
author: "MySQL 기술 노트"
source_url: ""
---

## 1. 복제본의 수보다 중요한 세 가지 질문

MySQL 서버를 여러 대 운영한다고 해서 장애 시 쓰기를 계속해도 되는 서버가 자동으로 결정되는 것은 아니다. 서로 통신할 수 없는 두 서버가 각각 자신을 정상 writer로 판단하면 데이터 이력이 갈라진다. 반대로 모든 서버의 응답을 기다리게 하면 한 대의 장애가 전체 쓰기를 멈추게 한다.

Group Replication은 이 문제를 **누가 그룹에 속하는가(membership), 어느 집합이 결정을 계속할 수 있는가(quorum), 함께 실행된 변경 중 무엇을 커밋할 수 있는가(certification)**로 나누어 다룬다. 세 개념은 연결되어 있지만 같은 기능이 아니다. 과반수가 있다는 사실만으로 업무 충돌이 해결되지는 않으며, 충돌 인증이 성공했다고 모든 멤버에서 즉시 최신 값을 읽는 것도 아니다.

이 글은 MySQL 8.0 및 8.4 계열의 개념과 관측 방법을 다룬다. SQL은 폐기용 단일 MySQL 8.0 인스턴스에서 실행한다. **검증 범위는 과반수 계산과 진단 객체·열의 존재, 조회 실행이다. 실제 그룹 구성, 네트워크 분리, 인증 충돌, 자동 승격은 이번 시험에 포함하지 않았다.** 진단 결과가 비어 있는 경우도 그대로 제시하고 그 의미를 구분한다.

## 2. 트랜잭션 실행에서 그룹 합의까지

일반적인 비동기 복제에서는 source의 커밋과 replica의 수신·적용이 분리된다. Group Replication은 로컬에서 실행한 변경 트랜잭션을 최종 커밋하기 전에 그룹 통신과 충돌 인증 절차를 거치게 한다. 각 서버는 자체 InnoDB 데이터와 로그를 보유한다. 여러 서버가 하나의 데이터 파일을 함께 여는 구조가 아니다.

동작을 다음과 같이 구분하면 이해하기 쉽다.

1. **로컬 실행:** SQL을 실행하고 InnoDB의 로컬 잠금과 MVCC 규칙을 따른다. 변경 행의 식별 정보로 write set을 만든다.
2. **순서 결정:** 변경 내용과 인증에 필요한 정보를 그룹으로 전달한다. 그룹 통신 계층은 멤버들이 같은 순서로 트랜잭션을 판단할 수 있도록 조정한다.
3. **인증:** 각 멤버는 같은 순서와 인증 정보를 바탕으로 동시 실행된 변경 간 충돌을 판정한다. 충돌하면 원래 실행한 트랜잭션을 롤백한다.
4. **커밋·적용:** 인증을 통과한 변경을 원래 멤버에서 커밋하고 다른 멤버의 applier에서 적용한다. 다른 멤버의 적용 완료를 언제까지 기다릴지는 일관성 설정에도 영향을 받는다.

```mermaid
flowchart TD
    A[클라이언트 변경 트랜잭션] --> B[로컬 InnoDB 실행과 write set 생성]
    B --> C[현재 멤버십과 과반수 기반 순서 결정]
    C --> D[멤버별 동일 순서의 충돌 인증]
    D -->|충돌| E[원래 트랜잭션 롤백]
    D -->|통과| F[원래 멤버의 커밋]
    D -->|통과| G[다른 멤버의 적용 큐와 applier]
    F --> H[일관성 수준에 따른 완료 응답]
    G -. 적용 대기가 필요한 수준 .-> H
```

그림은 기능 간 관계를 단순화한 것이다. 메시지 합의, 충돌 인증, 각 서버의 InnoDB 커밋, 클라이언트 응답을 하나의 시점으로 취급해서는 안 된다. 특히 “그룹에 전달됨”과 “다른 멤버의 SELECT에서 보임” 사이에는 적용 지연과 트랜잭션 스냅샷이라는 별도 경계가 있다.

## 3. quorum: 과반수는 데이터 정확성의 투표가 아니다

quorum은 그룹이 계속 결정을 내릴 수 있는 참여 규모다. 같은 멤버십을 기준으로 과반수 집합은 서로 겹치므로, 분리된 두 집합이 각각 독립적으로 정상 합의를 계속하는 것을 막는 기반이 된다. 이는 행의 값을 여러 서버에서 읽어 다수결로 고르는 기능이 아니다.

멤버 수가 `n`일 때 과반수는 `FLOOR(n / 2) + 1`이다. 다음 SQL은 실제 클러스터 상태를 읽지 않고 **가정한 그룹 크기**에 대한 과반수와 동시 장애 허용 수를 계산한다.

```sql
SELECT n AS group_size,
       FLOOR(n / 2) + 1 AS required_majority,
       n - (FLOOR(n / 2) + 1) AS tolerated_failures
FROM (
    SELECT 2 AS n UNION ALL SELECT 3
    UNION ALL SELECT 4 UNION ALL SELECT 5
) AS sizes
ORDER BY n;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT n AS group_size,
    ->        FLOOR(n / 2) + 1 AS required_majority,
    ->        n - (FLOOR(n / 2) + 1) AS tolerated_failures
    -> FROM (
    ->     SELECT 2 AS n UNION ALL SELECT 3
    ->     UNION ALL SELECT 4 UNION ALL SELECT 5
    -> ) AS sizes
    -> ORDER BY n;

+------------+-------------------+--------------------+
| group_size | required_majority | tolerated_failures |
+------------+-------------------+--------------------+
|          2 |                 2 |                  0 |
|          3 |                 2 |                  1 |
|          4 |                 3 |                  1 |
|          5 |                 3 |                  2 |
+------------+-------------------+--------------------+
4 rows in set (0.00 sec)
```

두 멤버 구성은 한 멤버를 잃으면 과반수를 유지하지 못한다. 세 멤버 구성은 한 멤버의 갑작스러운 장애를 견딜 수 있다. 네 멤버는 세 멤버보다 동시 장애 허용 수가 늘지 않지만, 다섯 멤버는 두 멤버의 장애를 견딜 수 있다. 다만 멤버 수 증가에는 통신·인증·저장·적용 비용이 따른다.

### 멤버십 변경과 장애를 구별해야 한다

이 계산은 **주어진 멤버십에서 갑자기 통신할 수 없어진 멤버**를 가정한다. 정상 탈퇴를 합의하여 새로운 view가 설치된 경우와, 과반수를 잃은 상황에서 남은 서버가 제멋대로 분모를 줄이는 경우는 다르다. 세 멤버 중 자신만 보인다고 해서 “현재 보이는 서버는 한 대이므로 과반수 충족”이라고 판단할 수 없다.

세 멤버가 두 멤버와 한 멤버로 분리되면 과반수 측은 필요한 장애 감지·재구성 절차를 거쳐 진행할 수 있다. 소수 측은 정상적인 그룹 결정에 참여할 수 없다. 소수 측 mysqld의 프로세스나 SQL 포트가 살아 있다는 사실은 쓰기 서비스의 정상성을 보장하지 않는다. 설정에 따라 대기, 그룹 이탈, 재가입 시도, 종료 동작 등이 달라질 수 있다.

물리적 장애 영역도 중요하다. 여러 mysqld를 같은 호스트에 올려 얻은 멤버 수는 호스트 장애 내성과 같지 않다. AZ 장애를 고려한다면 해당 AZ가 사라졌을 때 남는 멤버와 네트워크 경로를 함께 계산해야 한다. 단순 홀수 배치만으로 공통 전원·네트워크·운영 실수의 위험이 사라지지 않는다.

## 4. certification: 로컬 잠금과 다른 충돌 판정

InnoDB 잠금은 한 서버 안에서 동시 변경을 조정한다. 서로 다른 멤버에서 실행되는 두 트랜잭션은 상대 서버의 로컬 행 잠금을 기다리는 방식으로 직렬화되지 않는다. Group Replication은 로컬에서 우선 실행한 뒤, 커밋 단계에서 write set과 트랜잭션의 실행 관계를 이용해 충돌을 판정하는 낙관적 접근을 사용한다.

예를 들어 multi-primary 환경의 서로 다른 멤버에서 같은 계정 행을 동시에 변경하면, 각 로컬 실행은 진행될 수 있어도 인증 단계에서는 양쪽 모두가 그대로 커밋할 수 있다고 보장할 수 없다. 먼저 정해진 순서와 충돌 관계에 따라 한쪽이 거부될 수 있다. **동시에 실행된 같은 행 변경**이 핵심이며, 나중 트랜잭션이 앞선 변경을 반영한 상태에서 순차적으로 같은 행을 수정하는 경우까지 전부 충돌이라고 부르는 것은 잘못이다.

인증은 또한 업무 규칙 전체를 이해하지 않는다. 서로 다른 행에 기록된 두 예약이 같은 외부 자원을 초과 예약하는 문제처럼, 데이터베이스의 행·키 제약으로 표현되지 않은 불변식은 별도의 설계가 필요하다. multi-primary를 도입했다고 서로 다른 행에 걸친 모든 업무 경합이 자동 해결되는 것은 아니다.

### 스키마와 애플리케이션의 책임

- 복제 대상 테이블에는 InnoDB와 명시적 PRIMARY KEY를 기본 설계로 사용한다. Group Replication은 모든 열이 NOT NULL인 UNIQUE KEY도 primary key equivalent로 인정하지만, InnoDB의 내부 숨은 행 ID를 적격 키로 간주해서는 안 된다.
- 큰 트랜잭션은 write set, 메시지, 인증 및 적용 큐에 부담을 준다. 가능한 경우 업무 원자성을 해치지 않는 단위로 나눈다.
- 인증 실패 시에는 전체 업무 트랜잭션의 경계에서 제한 횟수·지연을 둔 재시도를 설계한다. 일부 SQL만 맹목적으로 반복하지 않는다.
- 커밋 응답을 받기 전에 연결이 끊어진 경우는 명확한 롤백 오류와 다르다. 멱등 키와 업무 결과 조회로 커밋 여부를 확인해야 한다.
- 결제·메시지 발송 등 DB 밖의 부수 효과를 재시도할 때 중복 수행되지 않도록 outbox 또는 별도의 멱등 처리 경계를 둔다.

single-primary는 쓰기 진입점을 하나로 제한하여 멤버 사이의 쓰기 경합 설계를 단순하게 한다. 그렇다고 그룹 합의와 인증 계층이 사라지지는 않으며, 로컬 deadlock·잠금 대기·대형 트랜잭션 비용도 남는다. multi-primary는 모든 멤버에서 쓰기를 받을 수 있는 모드이지, writer 수에 비례해 성능이 증가하는 분산 샤딩 기능이 아니다.

## 5. membership: 살아 있는 프로세스와 정상 멤버는 다르다

membership은 그룹에 참여하는 서버 집합을 정의한다. 이 집합의 특정 구성을 view라고 하며, 가입·탈퇴·장애 감지로 재구성이 일어나면 view가 바뀐다. 그룹은 트랜잭션 순서뿐 아니라 멤버십 변경에도 합의해야 한다.

새 멤버는 기존 멤버로부터 필요한 상태를 받아 따라잡는 distributed recovery를 거친다. 환경에 따라 binlog 기반 상태 전송이나 clone을 사용한다. `RECOVERING`을 단순 접속 성공과 혼동하거나, 복구 중인 노드를 즉시 일반 read/write 대상에 넣어서는 안 된다.

주요 상태는 다음과 같이 해석한다.

- `ONLINE`: 그룹 참여 상태다. 그러나 모든 시점의 적용 큐가 비었다는 뜻은 아니다.
- `RECOVERING`: 그룹에 합류하기 위해 상태를 복구하고 있다. 장기화하면 recovery 채널, donor, 인증·네트워크·로그 보존 상태를 확인한다.
- `UNREACHABLE`: 관측하는 멤버에서 다른 멤버에 대한 통신 장애가 감지되었다. 상대 mysqld가 실제로 종료되었다는 증거와 같지 않다.
- `OFFLINE`: Group Replication이 실행 중이 아닌 상태다. mysqld 자체는 실행 중일 수 있다.
- `ERROR`: 그룹 복제 처리 중 오류가 발생한 상태다. error log와 적용 오류를 함께 조사한다.

장애 감지에는 시간이 필요하다. 일시적인 네트워크 흔들림, CPU 정체, 긴 스케줄링 지연을 영구 장애처럼 취급하면 불필요한 추방과 복구가 반복된다. 반대로 대기 시간을 과도하게 늘리면 장애 시 쓰기 지연과 서비스 전환 시간이 길어진다. `group_replication_member_expel_timeout`, `group_replication_unreachable_majority_timeout`, `group_replication_autorejoin_tries`, `group_replication_exit_state_action`은 각각 다른 국면을 제어하므로 하나의 “failover timeout”으로 묶지 않는다.

## 6. 진단 SQL: 존재·멤버십·인증·적용을 분리한다

### 6.1 진단 객체가 있다는 것과 그룹을 운영한다는 것은 다르다

다음은 서버 버전, 플러그인 활성 여부와 진단 테이블의 존재를 조회한다. 이 시험은 Group Replication 플러그인을 설치·시작하지 않은 단일 인스턴스다. `active_gr_plugins = 0`은 해당 시험 조건을 나타내며, 운영에 권장하는 설정이 아니다.

```sql
SELECT VERSION() AS mysql_version,
       (SELECT COUNT(*) FROM information_schema.PLUGINS
        WHERE PLUGIN_NAME = 'group_replication'
          AND PLUGIN_STATUS = 'ACTIVE') AS active_gr_plugins;

SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'performance_schema'
  AND TABLE_NAME IN ('replication_group_members',
                     'replication_group_member_stats')
ORDER BY TABLE_NAME;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT VERSION() AS mysql_version,
    ->        (SELECT COUNT(*) FROM information_schema.PLUGINS
    ->         WHERE PLUGIN_NAME = 'group_replication'
    ->           AND PLUGIN_STATUS = 'ACTIVE') AS active_gr_plugins;

+---------------+-------------------+
| mysql_version | active_gr_plugins |
+---------------+-------------------+
| 8.0.46        |                 0 |
+---------------+-------------------+
1 row in set (0.00 sec)

mysql> SELECT TABLE_NAME
    -> FROM information_schema.TABLES
    -> WHERE TABLE_SCHEMA = 'performance_schema'
    ->   AND TABLE_NAME IN ('replication_group_members',
    ->                      'replication_group_member_stats')
    -> ORDER BY TABLE_NAME;

+--------------------------------+
| TABLE_NAME                     |
+--------------------------------+
| replication_group_member_stats |
| replication_group_members      |
+--------------------------------+
2 rows in set (0.00 sec)
```

테이블 두 개가 존재하더라도 그룹이 구성되었다는 뜻은 아니다. 실제 도입 시에는 binlog, ROW 형식, GTID, 고유한 서버 식별자, 복제 대상 테이블의 키, 멤버 간 양방향 통신, 복구용 계정과 인증서까지 별도로 확인한다. MySQL 8.0용 설정 파일의 모든 항목을 8.4에 그대로 복사하지 말고 해당 버전의 요구 사항을 기준으로 검사한다.

### 6.2 멤버십과 역할 관측

```sql
SELECT MEMBER_ID, MEMBER_HOST, MEMBER_PORT,
       MEMBER_STATE, MEMBER_ROLE, MEMBER_VERSION
FROM performance_schema.replication_group_members
ORDER BY MEMBER_ID;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT MEMBER_ID, MEMBER_HOST, MEMBER_PORT,
    ->        MEMBER_STATE, MEMBER_ROLE, MEMBER_VERSION
    -> FROM performance_schema.replication_group_members
    -> ORDER BY MEMBER_ID;

Empty set (0.00 sec)
```

이 시험에서 `Empty set`은 플러그인이 활성화되지 않았다는 앞선 조회와 일치한다. 정상 운영 그룹에서 멤버를 확인한 출력이 아니다. 운영에서는 의도한 멤버 목록과 실제 `MEMBER_STATE`, `MEMBER_ROLE`을 대조한다. single-primary의 정상 상태라면 쓰기 역할의 primary가 누구인지 확인하고 Router·프록시가 같은 대상을 가리키는지도 검사한다.

한 서버의 조회를 전체 네트워크의 객관적 시야로 간주하지 않는다. 장애가 의심되면 접근 가능한 여러 멤버에서 시각을 맞춰 관측하고, error log의 가입·추방·승격 기록을 대조한다. 모니터링 시스템의 수집 실패도 별도 장애 신호로 취급해야 한다.

### 6.3 인증 큐와 적용 큐를 구분한다

```sql
SELECT MEMBER_ID, VIEW_ID,
       COUNT_TRANSACTIONS_IN_QUEUE AS certification_queue,
       COUNT_CONFLICTS_DETECTED AS conflicts_detected,
       COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE AS applier_queue
FROM performance_schema.replication_group_member_stats
ORDER BY MEMBER_ID;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT MEMBER_ID, VIEW_ID,
    ->        COUNT_TRANSACTIONS_IN_QUEUE AS certification_queue,
    ->        COUNT_CONFLICTS_DETECTED AS conflicts_detected,
    ->        COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE AS applier_queue
    -> FROM performance_schema.replication_group_member_stats
    -> ORDER BY MEMBER_ID;

Empty set (0.00 sec)
```

이 결과 역시 그룹이 없는 시험 환경에서는 비어 있다. 빈 결과를 “충돌과 지연이 모두 0”으로 변환해서는 안 된다. 운영 모니터링에서는 **관측 대상 없음**, **수집 실패**, **실제 0**을 분리한다.

- `certification_queue`는 인증 처리를 기다리는 트랜잭션 수다. 증가가 지속된다면 유입률과 그룹 통신·인증 처리 경로를 함께 본다.
- `conflicts_detected`는 인증에서 감지한 충돌의 누적 수다. 절대값 하나보다 같은 멤버·비교 가능한 구간에서의 증가량을 보고 업무 실패율과 연결한다. 재시작이나 상태 초기화를 가로질러 단순 차분하지 않는다.
- `applier_queue`는 원격 트랜잭션 중 로컬 적용을 기다리는 큐다. 특정 멤버에서만 계속 증가하면 해당 멤버의 CPU·I/O·잠금·applier 상태를 조사한다.
- `VIEW_ID`는 통계가 속한 그룹 구성을 구분하는 단서다. 서로 다른 시점의 멤버 목록과 통계를 무조건 한 상태로 합치지 않는다.

원격 멤버 통계는 주기적으로 공유되므로 조회하는 멤버의 로컬 값과 완전히 같은 시점의 관측이 아니다. 또한 큐 길이는 시간 단위 지연이 아니다. 큰 트랜잭션 하나와 작은 트랜잭션 여러 개의 적용 비용은 다르다. flow control은 뒤처진 멤버 때문에 유입을 조절할 수 있어, writer의 CPU 사용률이 낮아도 전체 처리량이 제한될 수 있다.

## 7. 커밋 성공, 최신 읽기, 접속 전환은 별도 계약이다

Group Replication을 “모든 복제본에 즉시 적용되는 동기 복제”라고만 설명하면 읽기 경로에서 문제가 생긴다. `group_replication_consistency`의 대표적인 선택은 다음과 같다.

- `EVENTUAL`: 읽기 전에 선행 변경 적용을 별도로 기다리지 않으며, 쓰기도 다른 멤버의 적용 완료를 기다리지 않는다. 다른 멤버에서 오래된 값을 읽을 수 있다.
- `BEFORE_ON_PRIMARY_FAILOVER`: 새 primary가 이전 primary의 backlog를 처리하는 동안 새 트랜잭션을 대기시켜 승격 직후의 일관성을 보호한다. 평상시 모든 secondary 읽기의 최신성을 의미하지는 않는다.
- `BEFORE`: 트랜잭션 실행 전에 앞선 변경의 적용을 기다리는 방식이다. 최신 읽기가 필요한 세션의 지연 비용과 함께 검토한다.
- `AFTER`: 변경 트랜잭션이 다른 ONLINE 멤버에 적용될 때까지 기다린다. 쓰기 지연과 느린 멤버의 영향을 감수하는 선택이다.
- `BEFORE_AND_AFTER`: 실행 전과 변경 후의 대기를 결합한다.

이들은 개념적 비교이며 이번 단일 서버 시험에서 해당 보장을 실험한 결과가 아니다. 실제 기본값과 세션값은 대상 버전·구성에서 확인한다. 이미 열린 InnoDB consistent read 스냅샷을 자동으로 새 스냅샷으로 바꾸는 기능으로 해석해서도 안 된다.

또한 primary 선출은 기존 애플리케이션 연결을 새 서버로 옮기는 기능이 아니다. 일반적으로 MySQL Shell의 AdminAPI로 InnoDB Cluster를 관리하고 MySQL Router 등을 통해 연결을 라우팅하지만, 커넥션 풀의 재연결·오류 처리·멱등 재시도는 여전히 필요하다. Group Replication 플러그인 자체와 이를 운영하기 위한 관리·라우팅 계층을 구분해야 한다.

## 8. 장애 대응과 Aurora MySQL의 경계

과반수를 잃어 쓰기가 멈춘 상태는 데이터 이력이 갈라지는 것을 막기 위한 보호 동작일 수 있다. 복구를 서두르면서 서로 분리된 양쪽에서 bootstrap이나 강제 멤버십 변경을 수행하면 그 보호를 우회할 수 있다. 강제 복구 전에 이전 writer 및 분리된 집합의 쓰기를 확실히 차단하고, 각 서버의 이력과 데이터 상태를 확인하며, 어느 집합을 기준으로 복구할지 결정해야 한다. 이 글에서는 복사해서 실행할 수 있는 강제 복구 명령을 제시하지 않는다.

실무 대응 순서는 **연결·통신 상태 확인 → 여러 멤버의 view와 역할 대조 → 인증/적용 오류 및 큐 확인 → 라우팅·세션 일관성 확인 → 복구 방식 결정**이다. `super_read_only`를 해제해서 쓰기가 되게 만드는 조치는 그룹 건전성을 복구하는 것과 다르다. 재가입이나 clone을 결정하기 전에도 donor의 데이터, 로그 보존, 복구 계정, 네트워크와 여유 용량을 확인한다.

Aurora MySQL의 같은 클러스터 내 writer·reader는 공유 클러스터 볼륨을 이용하는 Aurora의 복제·고가용성 모델이다. Community MySQL Group Replication 멤버 수의 과반수 계산을 Aurora reader 수에 대입해서는 안 된다. Aurora reader 하나를 추가하는 행위를 Group Replication의 voting member 추가로 볼 수도 없다.

Aurora에서는 클러스터 endpoint, reader endpoint, failover 대상, replica lag와 버전별 일관성 기능을 기준으로 운영한다. Aurora 외부와의 binlog 복제도 같은 클러스터 내부의 복제와 구별한다. 여기서 제시한 Group Replication 전용 Performance Schema 결과를 Aurora 고가용성의 정상 여부 판정 기준으로 사용하지 않는다.

## 9. 도입·점검 체크리스트

- [ ] quorum을 계산할 때 현재 합의된 멤버십과 장애 영역을 함께 고려했는가?
- [ ] single-primary와 multi-primary 중 어떤 모드가 업무 쓰기 경합에 맞는지 결정했는가?
- [ ] 복제 대상의 InnoDB 사용과 PRIMARY KEY 또는 적격한 비NULL UNIQUE KEY를 확인했는가?
- [ ] 인증 충돌, 로컬 deadlock, 적용 오류, 커밋 결과 미확정을 구별하는가?
- [ ] 멤버십·역할·인증 큐·적용 큐를 별도로 수집하고 관측 누락을 0으로 바꾸지 않는가?
- [ ] `ONLINE`을 적용 지연 없음이나 모든 읽기의 최신성으로 해석하지 않는가?
- [ ] 일관성 수준과 커넥션 풀·라우팅·재시도 정책을 함께 검증했는가?
- [ ] 과반수 상실 시 강제 복구 전에 이전 writer를 차단하는 절차가 있는가?
- [ ] 실제 다중 서버 시험에서 네트워크 분리·재가입·승격·응답 미확정을 확인했는가?
- [ ] Group Replication이 잘못된 DELETE도 복제한다는 점을 고려해 별도 백업·복구 체계를 유지하는가?

## 10. 정리

membership은 참여 집합을, quorum은 결정을 계속할 조건을, certification은 동시 변경의 충돌 판정을 담당한다. 세 계층 위에 각 멤버의 적용 속도와 애플리케이션 읽기 일관성, 접속 라우팅이 더해져 실제 서비스의 가용성이 결정된다.

첫 도입에서는 멤버를 늘리거나 강한 일관성 수준을 일괄 설정하기보다, 실패 시 어떤 변경이 확정되고 어느 읽기 경로에서 언제 보이는지부터 정의해야 한다. 다음 단계에서는 single-primary의 primary 선출과 네트워크 파티션 복구를 실제 다중 서버 시험으로 확인하면 이 개념을 운영 절차로 연결할 수 있다.

## 참고 자료

- [MySQL 8.4: Group Membership](https://dev.mysql.com/doc/refman/8.4/en/group-replication-group-membership.html)
- [MySQL 8.4: Fault-tolerance](https://dev.mysql.com/doc/refman/8.4/en/group-replication-fault-tolerance.html)
- [MySQL 8.4: Group Replication Requirements](https://dev.mysql.com/doc/refman/8.4/en/group-replication-requirements.html)
- [MySQL 8.4: Monitoring Group Replication](https://dev.mysql.com/doc/refman/8.4/en/group-replication-monitoring.html)
- [MySQL 8.4: Configuring Transaction Consistency Guarantees](https://dev.mysql.com/doc/refman/8.4/en/group-replication-configuring-consistency-guarantees.html)
- [AWS: Replication with Amazon Aurora](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Replication.html)
