Postmortem: Menangani “Too Many Connections” pada MySQL

Skenario: pukul 01:00 UTC website mulai mengembalikan 503. Log menunjukkan SQLSTATE[08004] [1040] Too many connections. Menurut manual MySQL, error terjadi ketika seluruh koneksi yang diizinkan sedang digunakan; batas dikendalikan oleh max_connections.
Dampak#
- Request yang membutuhkan database gagal selama 11 menit.
- Halaman statis tetap tersedia.
- Tidak ada kehilangan data yang teridentifikasi.
- Analytics kehilangan sebagian event selama pemulihan.
Timeline contoh#
| UTC | Peristiwa |
|---|---|
| 00:58 | Traffic crawler meningkat 4× |
| 01:00 | Active connections menyentuh limit |
| 01:02 | Alert 5xx aktif |
| 01:05 | On-call memeriksa process list |
| 01:08 | Endpoint mahal dibatasi |
| 01:11 | Error rate normal |
Diagnosis#
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Threads_running';
SHOW FULL PROCESSLIST;
Threads_connected tinggi tetapi Threads_running rendah mengarah pada banyak koneksi idle. Banyak query state “Sending data” atau lock membutuhkan analisis berbeda. Periksa juga jumlah PHP worker: concurrency aplikasi × instance harus masuk budget database.
Five whys yang konkret#
- Mengapa request gagal? Semua slot koneksi terpakai.
- Mengapa slot penuh? Worker PHP menahan koneksi lebih lama saat query analytics lambat.
- Mengapa query lambat? Index pada kolom waktu tidak sesuai pola cleanup/report.
- Mengapa traffic memperparah? Endpoint dapat dipanggil crawler tanpa throttling.
- Mengapa terdeteksi terlambat? Alert hanya pada 5xx, bukan saturation connection.
Mitigasi segera#
- Rate-limit endpoint sumber beban.
- Hentikan job/report non-kritis.
- Kill query tertentu hanya setelah memastikan dampak transaksi.
- Naikkan limit sementara hanya bila memory dan kapasitas server mendukung.
- Pertahankan akses admin darurat sesuai kemampuan server dan kebijakan privilege.
Perbaikan permanen#
- Index query lambat dan batasi range laporan.
- Set timeout aplikasi/database yang masuk akal.
- Fail-open untuk analytics non-kritis.
- Budget koneksi per service dan instance.
- Alert pada 70/85/95% saturation.
- Load test sampai bottleneck terlihat.
- Runbook diagnosis yang tidak bergantung pada satu orang.
Apa yang tidak boleh ditulis#
“Developer lupa menutup koneksi” tanpa bukti. Pada PHP/PDO, lifetime request dan persistent connection memengaruhi perilaku; postmortem harus menunjukkan telemetry, konfigurasi, dan query. Fokus pada kondisi sistem yang memungkinkan kegagalan.
Action item baik: “Tambahkan dashboard Threads_connected/max_connections dan alert 85%, owner Platform, jatuh tempo 18 Agustus.” Action item buruk: “Lebih hati-hati.”
Connection budget#
DB limit aman: 200
Reserve admin/maintenance: 20
Budget aplikasi: 180
3 instances × 40 PHP workers = maksimum teoritis 120
Job/report budget = 30
Headroom = 30
Budget mencegah autoscaling aplikasi secara tidak sengaja melampaui kapasitas database. Jika persistent connection dipakai, pahami lifetime worker; jangan mengasumsikan koneksi ditutup setelah satu request.
Query dan index#
Connection saturation kadang gejala query lambat. Gunakan slow query log, execution plan, lock wait, dan histogram latency. Menambah koneksi ketika disk/CPU sudah jenuh dapat memperburuk antrean.
Game day#
- Turunkan limit di staging.
- Generate concurrency terkontrol.
- Pastikan alert saturation aktif sebelum 5xx.
- Ikuti runbook menggunakan akun admin yang tepat.
- Verifikasi optional feature fail-open.
- Ukur waktu recovery.
Definition of resolved#
Incident bukan selesai ketika service kembali hijau. Ia selesai ketika akar kondisi dipahami, action item memiliki owner/tanggal, alert diuji, dan perubahan kapasitas atau kode diverifikasi melalui load test.
💬 Comments (0)
No comments yet. Be the first to share your thoughts!