อาการที่เจอ
3-node Galera cluster อยู่ๆ มี node หลุด:
SHOW STATUS LIKE 'wsrep_cluster_size';
+---------------------+-------+
| wsrep_cluster_size | 2 | ← ปกติ 3
+---------------------+-------+
SHOW STATUS LIKE 'wsrep_local_state_comment';
+---------------------------+--------------+
| wsrep_local_state_comment | Disconnected |
+---------------------------+--------------+
หรือ:
[Warning] WSREP: Quorum: No node with complete state:
[ERROR] WSREP: Cluster member missing
ในกรณีร้ายแรง — ทั้ง 3 node "Disconnected" จาก quorum (split-brain) ทุกตัวอ่าน-เขียนไม่ได้
ก่อนแก้ — เข้าใจ Galera ก่อน
Galera = synchronous multi-master replication
- ทุก node เขียนได้พร้อมกัน
- ต้องมี quorum (เกินครึ่งของ cluster size) ถึงจะรับ write
- Cluster 3 node — ต้องมี 2 node alive ขึ้นไปถึงจะทำงาน
ถ้า node ส่วนใหญ่หายไป — ที่เหลือเข้า "non-Primary" state รับ write ไม่ได้ — กันไม่ให้ split-brain
ขั้นตอน Debug
Step 1: ดูสถานะแต่ละ node
ใน node ทุกตัวรัน:
SHOW STATUS LIKE 'wsrep_%';
ดู value เหล่านี้:
| Variable | ความหมาย |
|---|---|
| wsrep_cluster_size | จำนวน node ใน cluster ตอนนี้ |
| wsrep_cluster_status | Primary = ดี, non-Primary = ปัญหา |
| wsrep_connected | ON = connect ใน cluster อยู่ |
| wsrep_ready | ON = รับ query ได้ |
| wsrep_local_state_comment | Synced = ดี, อื่นๆ = ดู status |
Step 2: ดู error log
sudo tail -100 /var/log/mysql/error.log
หรือใน Docker:
docker logs --tail 200 mariadb
มอง keyword:
WSREP— เกี่ยวกับ GaleraConnection refused— node ติดต่อกันไม่ได้gcomm— group communicationSST/IST— state transfer
Step 3: ตรวจ network ระหว่าง node
Galera ใช้ port:
- 3306 — MySQL client
- 4567 — Galera replication (TCP + UDP)
- 4568 — IST (incremental state transfer)
- 4444 — SST (snapshot state transfer)
ตรวจจาก node A → node B:
nc -zv node-b 3306
nc -zv node-b 4567
nc -zv node-b 4568
nc -zv node-b 4444
ถ้า port ไหนเชื่อมไม่ได้ — firewall block
# Ubuntu ufw
sudo ufw allow from 10.0.0.0/24 to any port 3306,4444,4567,4568 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 4567 proto udp
วิธีกู้คืน
Case A: 1 node หลุดจาก 3
ปกติ node ที่หลุดจะกลับเข้ามาเอง — ตรวจ status:
sudo systemctl status mariadb
ถ้า service ยังรัน restart:
sudo systemctl restart mariadb
ดู log ว่า rejoin ได้มั้ย:
sudo tail -f /var/log/mysql/error.log
ควรเห็น:
[Note] WSREP: Member ... synced with group
[Note] WSREP: ... SYNCED -> JOINED
Case B: ทุก node Disconnected (split-brain)
ทุก node "non-Primary" — ใครจะ start cluster ก่อน?
ขั้นที่ 1: หา node ที่ commit transaction ล่าสุด
ใน node แต่ละตัวรัน:
sudo cat /var/lib/mysql/grastate.dat
ดู:
seqno: 1842903
node ที่ seqno สูงสุด = มี data ใหม่ที่สุด = ควร bootstrap cluster
ถ้า seqno = -1:
sudo mysqld_safe --wsrep-recover
# จะเห็น "Recovered position: <uuid>:<seqno>"
ขั้นที่ 2: bootstrap จาก node นั้น
หยุด mariadb ทุก node ก่อน:
sudo systemctl stop mariadb
บน node ที่ seqno สูงสุด — set safe_to_bootstrap = 1:
sudo nano /var/lib/mysql/grastate.dat
safe_to_bootstrap: 1
bootstrap:
sudo galera_new_cluster
# หรือ
sudo systemctl start mariadb@bootstrap
ตรวจสอบ:
SHOW STATUS LIKE 'wsrep_cluster_status';
-- Primary
ขั้นที่ 3: start node อื่นกลับเข้า cluster
# บน node 2 และ 3
sudo systemctl start mariadb
node อื่นจะ SST/IST จาก node แรก แล้ว sync
SHOW STATUS LIKE 'wsrep_cluster_size';
-- 3
Case C: SST stuck
ถ้า node ใหม่ join แล้วค้างที่ "Joiner" นาน — SST อาจช้า/ค้าง
ตรวจ:
ps aux | grep -E "rsync|xtrabackup|mariabackup"
ถ้าไม่มี process — restart node:
sudo systemctl restart mariadb
ลด SST timeout / เปลี่ยน method ใน config:
/etc/mysql/mariadb.conf.d/galera.cnf:
wsrep_sst_method=mariabackup # เร็วกว่า rsync
wsrep_sst_auth=sstuser:password
ป้องกันการหลุดในอนาคต
1. ใช้ network เสถียร — ไม่ใช่ public internet
Galera ไวกับ latency มาก — > 100ms = อาจ flaky
ใช้:
- VPC/private network ของ cloud provider
- VPN เช่น Tailscale / WireGuard
- Direct connect ระหว่าง data center
2. Tune timeout ให้รับ latency
galera.cnf:
# default 5s — เพิ่มถ้า latency สูง
wsrep_provider_options="evs.suspect_timeout=PT15S;evs.inactive_timeout=PT45S;evs.keepalive_period=PT3S"
3. เปิด arbitrator ถ้ามี 2 node
Cluster 2 node = ถ้า node ตาย → quorum หาย ทั้ง cluster อ่านไม่ได้
ใช้ Galera Arbitrator (garbd) — node "พิเศษ" ที่ไม่เก็บ data แต่ vote ด้วย
sudo apt install galera-arbitrator-3
config /etc/default/garb:
GALERA_NODES="10.0.0.1:4567,10.0.0.2:4567"
GALERA_GROUP="my_cluster"
เปิดเป็น service:
sudo systemctl enable --now garb
4. Monitor + Alert
ตั้ง alert ใน Prometheus / Uptime Kuma:
mysql_global_status_wsrep_cluster_size < 3
mysql_global_status_wsrep_local_state{state!="Synced"}
หรือเขียน script เช็ค:
#!/bin/bash
SIZE=$(mysql -e "SHOW STATUS LIKE 'wsrep_cluster_size';" | awk 'NR==2 {print $2}')
if [ "$SIZE" != "3" ]; then
curl -X POST $SLACK_WEBHOOK -d '{"text":"⚠️ Galera cluster size: '"$SIZE"'"}'
fi
cron ทุก 5 นาที
5. Backup ข้อมูลด้วย mariabackup
อย่าพึ่ง replication อย่างเดียว — Galera replicate bug/delete กระจายทันที
ตั้ง backup รายวัน:
mariabackup --backup --target-dir=/data/backup/$(date +%F) \
--user=backup --password=...
ดูเพิ่ม: Backup Database อัตโนมัติ
เครื่องมือช่วย debug
# Node status สรุปย่อ
mysql -e "SHOW STATUS LIKE 'wsrep_%';" | grep -E "cluster_size|cluster_status|connected|local_state_comment|ready"
# ดู GTID history
mysql -e "SELECT @@gtid_current_pos;"
# ดู replication lag (ถ้ามี async slave ด้วย)
mysql -e "SHOW SLAVE STATUS\G" | grep Seconds_Behind_Master
เช็คลิสต์เวลาเจอ
- ✅ ดู
wsrep_cluster_size,wsrep_cluster_statusใน node ทุกตัว - ✅ ดู error log
- ✅ เช็ค network connectivity port 4567/4568/4444
- ✅ เช็ค seqno ใน
grastate.dat - ✅ ถ้าทุก node down → bootstrap จาก node ที่ seqno สูงสุด
- ✅ ตั้ง alert ป้องกันครั้งหน้า
สรุป
Galera หลุด เกือบทั้งหมดมาจาก network ระหว่าง node — ตรวจ network ก่อนเสมอ
ถ้าพังจริง ๆ — grastate.dat คือกุญแจ ดู seqno เพื่อรู้ว่า node ไหนจะ bootstrap
ป้องกันด้วย: network ที่ดี + arbitrator (ถ้า 2 node) + monitor + backup