dataiotech Labs
Runbook #63
mysql
AvailabilitySEV1 · CRITICAL OUTAGE15-30 dakika / 15-30 minsmysql administrator / CLUSTER_ADMIN / GROUP_REPLICATION_ADMIN

MySQL Group Replication / InnoDB Cluster: Node Unreachable & Split-Brain (NO_QUORUM) Recovery

Emergency recovery for MySQL Group Replication and InnoDB Cluster outages: handling OFFLINE/ERROR nodes, majority quorum loss (NO_QUORUM), and safe single-primary reboot without data loss.

Related Metrics:M14M15
#mysql#innodb-cluster#group-replication#split-brain#no-quorum#mysql-shell#high-availability

Operational Safety & Risk Notice

This runbook contains operational intervention steps; several are write-impacting (KILL, terminate, DROP, RESIZE). Verify in a staging environment first, and apply sequentially in production with verification.

🟢 Salt Okunur (Read-Only)·🟡 Geri Alınabilir (Reversible)·🔴 Yüksek Etkili / Geri Alınamaz (High Impact)

1. Symptom & Signals

- `performance_schema.replication_group_members` tablosunda düğüm durumu `UNREACHABLE`, `ERROR` veya `OFFLINE`.

- MySQL Shell `dba.getCluster().status()` çıktısında küme durumu `NO_QUORUM` veya `OK_PARTIAL`.

- MySQL Router 503 döndürür; yazma istekleri `The group is unable to process write transactions` hatasıyla reddedilir.

2. Business & Technical Impact

P1 Kritik Kesinti. Çoğunluk oyu (quorum) kaybolduğunda InnoDB Cluster yazma işlemlerini dondurur. Yanlış müdahale (geride kalmış bir düğümden bootstrap yapılması) asenkron verilerin üzerine yazılmasına ve split-brain veri kaybına neden olur.

3. Diagnosis & Root-Cause Analysis

🟢 Read-Only1. **Canlı herhangi bir düğüm üzerinden küme üyelerinin durumunu kontrol edin:**
sql
SELECT member_id, member_host, member_port, member_state, member_role, member_version
FROM performance_schema.replication_group_members;
-- STATE: ONLINE, OFFLINE, ERROR, UNREACHABLE
-- MEMBER_ROLE: PRIMARY / SECONDARY
🟢 Read-Only2. **MySQL Shell ile küme topolojisini ve quorum durumunu inceleyin:**
bash
mysqlsh root@mysql-node1:3306
javascript
dba.getCluster().status();
// Cluster status: OK, OK_PARTIAL, NO_QUORUM
🟢 Read-Only3. **Errorlog'da neden düştüğünü araştırın:**
bash
grep -i "group_replication" /var/log/mysql/error.log | tail -n 100
# Yaygın sebepler: network partition, disk doluluğu, OOM killer, flow control.
🟢 Read-Only4. **Karar Matrisi:**

- **1 node OFFLINE, cluster OK_PARTIAL:** Quorum sağlamdır; sadece o node'u güvenle rejoin edin.

- **2 node OFFLINE, NO_QUORUM (Split-Brain):** Quorum yoktur; en güncel GTID'li düğüm üzerinden reboot/force quorum yapılmalıdır.

- **Tüm node'lar UNREACHABLE:** Network / Firewall / DNS izolasyon kontrolü yapın.

4. Remediation & Action Plan

### Müdahale A: Tek Node OFFLINE — Güvenli Rejoin

javascript
// MySQL Shell ile OFFLINE node üzerinde:
var cluster = dba.getCluster();
cluster.rejoinInstance('root@mysql-node2:3306', {recoveryMethod: 'clone'});
cluster.status();

SQL ile manuel müdahale (MySQL Shell yoksa):

sql
-- OFFLINE düğüm üzerinde:
STOP GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;
START GROUP_REPLICATION;
-- 60 saniye içinde performance_schema tablosunda ONLINE görünmelidir.

---

### Müdahale B: Quorum Kaybı — NO_QUORUM (Split-Brain Kurtarma)

En kritik senaryo: 3 düğümlü kümede 2 düğüm düşmüş, kalan 1 düğüm tek başına yazamaz.

⚠️ **ALTIN KURAL: EN GÜNCEL GTID'E SAHİP DÜĞÜMÜ PRIMARY YAPIN!**

sql
-- Kalan canlı düğümlerde en son GTID'yi karşılaştırın:
SELECT @@GLOBAL.gtid_executed;
javascript
// En güncel görünen düğüme bağlanın:
// mysqlsh root@mysql-node1:3306

// 1. Quorum'u zorla geri getirin
dba.rebootClusterFromCompleteOutage();
// MySQL Shell size en güncel instance'ı teyit ettirecektir; en yüksek GTID'li olanı seçin.

// 2. Diğer düğümler fiziksel olarak geldikçe kümeye ekleyin:
var cluster = dba.getCluster();
cluster.rejoinInstance('root@mysql-node2:3306', {recoveryMethod: 'clone'});
cluster.rejoinInstance('root@mysql-node3:3306', {recoveryMethod: 'clone'});

Eğer `rebootClusterFromCompleteOutage()` çalışmazsa, son çare SQL manuel bootstrap:

sql
-- YALNIZCA EN GÜNCEL GTID'Lİ DÜĞÜMDE ÇALIŞTIRIN:
SET GLOBAL group_replication_bootstrap_group = ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group = OFF;

-- İkincil düğümlerde sadece:
START GROUP_REPLICATION;

5. Verification & Health Checks

- `SELECT * FROM performance_schema.replication_group_members;` -> Tüm üyeler `ONLINE`.

- `cluster.status()` -> Durum `OK` ve `cluster.checkInstanceState()` temiz.

- MySQL Router yönlendirme kontrolü:

bash
mysql -h mycluster-router -P 6446 -u app_user -p -e "SELECT @@hostname, @@global.group_replication_group_name;"

6. Rollback & Contingency Plan

- `rebootClusterFromCompleteOutage` sonrası yanlış bir düğümden ayağa kalkıldıysa, diğer düğümlere `clone` ile ezilmeden önce hemen binlog yedeği alınmalı ve `incremental recovery` denenmelidir.

- **Önleme Standartları — dbaguide Standardı:**

- [ ] `group_replication_unreachable_majority_timeout = 30` (varsayılan 0 yerine).

- [ ] `group_replication_autorejoin_tries = 3`.

- [ ] Network: Tüm düğümler arası 3306 ve 33061 (GR haberleşme portu) firewall açık mı?

- [ ] Disk: `innodb_cluster` metadata ve data dizinleri için ayrı izole depolama.

- [ ] PMM / Prometheus Alert: `MySQL Group Replication NOT ONLINE` alarmı aktif mi?

- [ ] Çeyreklik Chaos Engineering testi: 1 node kapatıldığında cluster kesintisiz yazmaya devam ediyor mu?

Engineering Triad: Diagnostic Scripts

Diagnostic scripts recommended during this runbook triage to pinpoint the root cause:

All Scripts (100)
#26 · SQLReplication

MySQL Replication Status and Lag Check

Checks IO/SQL thread state, Seconds_Behind_Source and the latest errors. Quickly verifies replica health.

#27 · SQLMonitoring

MySQL InnoDB Buffer Pool Hit Ratio

Compares buffer pool read requests against disk reads to compute the hit ratio. Tells you whether memory sizing is sufficient.

More MYSQL Runbooks