Seluruh section ini membangun asumsi diam-diam bahwa source selalu ada. Hari yang ditakuti datang ketika asumsi itu runtuh: disk source rusak pukul subuh, proses mysqld mati, atau mesinnya kehilangan daya. Failover adalah prosedur memindahkan peran “satu-satunya penerima tulis” dari source yang mati ke replica yang siap — dan seisi chapter ini menyiapkan kita menghadapinya dengan tenang: memahami durasinya dibanding sekadar me-restart server, menjaga replica agar tidak ditulis sembarangan, langkah-langkah promosi yang benar, serta bahaya paling mahal di dunia failover — split-brain. Karena tidak ada dua server di meja uji kita, perintah promosi akan dipajang sebagai prosedur, sementara semua yang bisa dibuktikan di satu server (perilaku read_only/super_read_only) kita uji sungguhan.
Failover vs Restart: Duel Durasi #
Ketika source mati, ada dua jalan pulih. Jalan pertama: hidupkan ulang server yang sama — mesin menjalankan crash recovery InnoDB (memutar ulang redo log, menggulung kembali transaksi yang tidak selesai), lalu aplikasi menyambung kembali. Durasinya bisa menit — dan itu bila kerusakannya pulih sendiri (mis. proses mysqld crash yang cukup di-restart); disk yang benar-benar mati butuh penggantian dan restore backup berjam-jam. Jalan kedua: failover — promosikan replica menjadi source dalam hitungan detik-menit, aplikasi dialihkan, layanan hidup lagi, sementara mesin rusak diperbaiki santai di belakang panggung.
| Strategi | RTO tipikal | Syarat |
|---|---|---|
| Restart server yang sama | Menit hingga jam | Kerusakan pulih sendiri (crash proses) |
| Failover manual | 1-5 menit (keputusan manusia) | Replica siap + prosedur latihan |
| Failover otomatis | Detik (deteksi + promosi) | Tool failover + fencing andal |
Failover bukan gratis: kita menukar waktu tunggu dengan kompleksitas dan risiko salah keputusan. Namun untuk sistem yang RTO-nya diukur menit, failover adalah satu-satunya pilihan yang realistis.
Menjaga Replica Bersih dari Tulis: read_only dan super_read_only #
Sebelum bicara promosi, replica harus dibesarkan dengan disiplin: tidak boleh ada tulisan selain dari SQL thread replikasi. Tulisan liar di replica membuat datanya menyimpang dari source — event replikasi berikutnya bisa gagal diterapkan (baris sudah tidak cocok) dan replica harus disinkronkan ulang dari nol. MySQL menyediakan dua tuas untuk disiplin ini, dan keduanya layak dibuktikan nyata. Kita siapkan meja uji kecil:
DROP DATABASE IF EXISTS belajar_repl;
CREATE DATABASE belajar_repl;
USE belajar_repl;
CREATE TABLE stok (
id INT AUTO_INCREMENT PRIMARY KEY,
barang VARCHAR(30) NOT NULL,
jumlah INT NOT NULL
);
INSERT INTO stok (barang, jumlah) VALUES
('Kopi Gayo', 40),
('Gula Aren', 25);Output yang Dihasilkan:
Query OK, 0 rows affected, 1 warning (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Database changed
Query OK, 0 rows affected (0.00 sec)
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0Kondisi awal server kita — kedua tuas mati, sebagaimana layaknya sebuah source. Karena read_only dan super_read_only adalah variabel global yang nilai awalnya bisa dipengaruhi percobaan sebelumnya, kita nol-kan dulu keduanya lalu membaca keadaannya:
SET GLOBAL read_only = OFF;
SET GLOBAL super_read_only = OFF;
SELECT @@GLOBAL.read_only AS read_only, @@GLOBAL.super_read_only AS super_read_only;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
+-----------+-----------------+
| read_only | super_read_only |
+-----------+-----------------+
| 0 | 0 |
+-----------+-----------------+
1 row in set (0.00 sec)Tuas pertama, read_only, memblokir tulisan dari koneksi biasa. Namun ada pengecualian besar yang sering mengejutkan: user dengan privilege administratif tetap boleh menulis. Kita nyalakan tuasnya lalu mencoba menulis sebagai root — dan dalam satu blok yang sama kita matikan kembali agar server tidak tertinggal dalam moda baca-saja:
SET GLOBAL read_only = ON;
SELECT @@GLOBAL.read_only AS read_only;
UPDATE stok SET jumlah = jumlah + 5 WHERE id = 1;
SET GLOBAL read_only = OFF;
SELECT id, barang, jumlah FROM stok WHERE id = 1;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
+-----------+
| read_only |
+-----------+
| 1 |
+-----------+
1 row in set (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Query OK, 0 rows affected (0.00 sec)
+----+-----------+--------+
| id | barang | jumlah |
+----+-----------+--------+
| 1 | Kopi Gayo | 45 |
+----+-----------+--------+
1 row in set (0.00 sec)UPDATE-nya berhasil (Query OK, 1 row affected) meski read_only bernilai 1 — karena koneksi kita sebagai root membawa privilege yang dikecualikan. Tuas kedua menutup lubang ini:
-- @error
SET GLOBAL super_read_only = ON;
UPDATE stok SET jumlah = 0 WHERE id = 2;
SET GLOBAL super_read_only = OFF;
SET GLOBAL read_only = OFF;
SELECT id, barang, jumlah FROM stok WHERE id = 2;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
+----+-----------+--------+
| id | barang | jumlah |
+----+-----------+--------+
| 2 | Gula Aren | 25 |
+----+-----------+--------+
1 row in set (0.00 sec)Kali ini server menolak dengan ERROR 1290 — super_read_only memblokir tulisan dari siapa pun (termasuk admin), dengan pengecualian terencana untuk SQL thread replikasi yang justru harus tetap bisa menerapkan event. Perhatikan baris terakhir: nilai Gula Aren tetap 25, bukti tulisan tidak pernah masuk. Dua statement pemulihan di akhir blok diperlukan karena mematikan super_read_only tidak otomatis mematikan read_only yang ikut menyala — pasangan tuas ini hanya bisa dipercaya bila kita mematikannya satu per satu. Jadi konfigurasi replica yang benar adalah read_only = ON dan super_read_only = ON — dua-duanya, karena satu-duanya punya celah.
Prosedur Manual: Mempromosikan Replica #
Failover manual adalah latihan disiplin berurutan. Setiap langkah punya alasan yang kalau dilewati akan dibayar mahal:
- Konfirmasi source mati dari dua titik berbeda. Bisa jadi hanya jalur jaringan ke server monitoring yang putus; mempromosikan replica saat source masih hidup adalah resep split-brain.
- Fencing source lama — pastikan ia tidak bisa menerima tulisan lagi: cabut daya (STONITH), blokir portnya di firewall, atau set
super_read_onlybila masih bisa diakses. Langkah ini harus selesai sebelum promosi. - Pilih replica paling maju: lag terkecil / posisi binlog terjauh. Data yang paling lengkap menjadi dasar klaster baru; replica lain akan mengejar kepadanya.
- Hentikan replikasi di kandidat:
STOP REPLICA;lalu verifikasiSeconds_Behind_Source = 0. - Putuskan ikatan ke source lama:
RESET REPLICA ALL;menghapus metadata koneksi sehingga kandidat berdiri sebagai server mandiri. - Buka gerbang tulis: matikan
read_onlydansuper_read_onlyseperti pada callout di atas. - Arahkan dunia ke source baru: aplikasi via VIP/DNS/proxy, dan replica lain via
CHANGE REPLICATION SOURCE TOyang menunjuk kandidat.
Langkah 4-6 dalam bentuk SQL (dijalankan di replica kandidat):
-- @notest
STOP REPLICA;
RESET REPLICA ALL;
SET GLOBAL read_only = OFF;
SET GLOBAL super_read_only = OFF;Dan langkah 7 di masing-masing replica lain:
-- @notest
STOP REPLICA;
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = '192.0.2.20',
SOURCE_PORT = 3306,
SOURCE_USER = 'repl',
SOURCE_PASSWORD = 'SandiRepl2026!',
SOURCE_AUTO_POSITION = 1;
START REPLICA;Parameter SOURCE_AUTO_POSITION = 1 memakai GTID sehingga replica lain mencari sendiri event yang belum dimilikinya dari source baru — inilah alasan topologi yang serius selalu menjalankan gtid_mode = ON sejak hari pertama; failover berbasis posisi file mengharuskan kita mencatat dan cocokkan posisi binlog secara manual.
Split-Brain: Dua Source yang Sama-Sama Yakin #
Split-brain terjadi bila dua server memainkan peran source pada saat bersamaan: source “mati” ternyata hidup kembali dan belum diberi tahu bahwa dunia sudah pindah. Aplikasi yang setengahnya masih menuju source lama menulis di sana, setengahnya lagi menulis di source baru — dua kenyataan yang berbeda, masing-masing “benar” menurut servernya. Konsekuensinya brutal: primary key tabrakan lintas-server, baris yang di-update di dua tempat dengan nilai berbeda, dan pada akhirnya salah satu kenyataan harus dibuang demi yang lain — kehilangan data yang dipilih, bukan yang terpaksa. Penyembuhannya praktis selalu restore ulang salah satu sisi. Itulah mengapa fencing (langkah 2) tidak boleh ditawar: sebelum replica dipromosikan, source lama harus kehilangan kemampuan menulis secara fisik atau administratif, bukan sekadar “kelihatannya mati”.
Otomasi, VIP, dan Failback #
Alat failover otomatis memampatkan langkah 1-7 di atas menjadi detik. MHA (Master High Availability) adalah veteran open-source yang memantau source, memilih replica paling maju, dan mempromosikannya. Orchestrator naik level di atasnya: memahami seluruh topologi replikasi (termasuk rantai), menyediakan antarmuka visual, dan melakukan controlled recovery — termasuk menata ulang replica-replica ke source baru secara otomatis. Keduanya bekerja di atas replikasi klasik; bila topologi memakai Group Replication/InnoDB Cluster, failover menjadi bagian protokolnya sendiri — klaster memilih primary baru lewat konsensus tanpa tool eksternal.
Pengalihan aplikasi sendiri biasanya tidak menyentuh kode: VIP (alamat IP yang berpindah antar mesin) atau DNS dengan TTL pendek membuat koneksi “mengikuti” server baru, atau proxy seperti ProxySQL/HAProxy yang tinggal mengubah kelompok server di belakangnya. Terakhir ada failback — mengembalikan source lama yang sudah diperbaiki ke klaster. Source lama tidak langsung kembali jadi source; ia bergabung dulu sebagai replica baru, disinkronkan mengejar source pengganti, dan hanya dipertimbangkan kembali menjadi source lewat keputusan terencana (bukan otomatis), karena transaksi yang sempat tertulis padanya sebelum mati harus direkonsiliasi dulu — biasanya dibuang bila klaster sudah lebih maju.
Checklist Keputusan Failover #
Latihan pemikiran penutup — saat alarm berbunyi pukul 3 pagi, keputusan harus mengalir dari daftar ini:
| Pertanyaan keputusan | Jawaban yang aman |
|---|---|
| Apakah source mati sungguhan? | Verifikasi dari 2+ titik, cek bukan sekadar jaringan |
| Apakah fencing berhasil? | Source lama dipastikan tidak bisa menerima tulisan |
| Replica mana yang dipromosikan? | Lag terkecil, Seconds_Behind_Source = 0 |
| Apakah aplikasi punya jalur pengalihan? | VIP/DNS/proxy siap, bukan edit konfigurasi manual |
| Siapa yang mengarahkan replica lain? | Prosedur GTID SOURCE_AUTO_POSITION terdokumentasi |
| Kapan failback? | Keputusan terjadwal, setelah source lama resync penuh |
Membersihkan Database Latihan #
DROP DATABASE belajar_repl;Output yang Dihasilkan:
Query OK, 1 row affected (0.00 sec)Referensi #
- Replication Solutions — MySQL 8.4 Reference Manual
- Replication Administration — MySQL 8.4 Reference Manual
- Group Replication — MySQL 8.4 Reference Manual
Kita kini punya prosedur lengkap untuk hari terburuk: fencing, promosi, pengalihan, dan disiplin split-brain. Satu pekerjaan terakhir menutup section ini — berjalan sebelum hari terburuk tiba: memahami apa yang replication tidak bisa berikan. Chapter Batasan Replication membongkar mitos terbesarnya (replikasi bukan backup), menunjukkan mengapa beban tulis tidak pernah turun, dan memetakan kapan saatnya naik kelas ke cluster sungguhan.