Daftar proses MySQL yang menampilkan banyak koneksi dalam keadaan sleep

Pesan mysql too many connections berarti batas koneksi bersamaan tercapai. Penyebabnya hampir selalu bukan batas yang terlalu kecil, melainkan koneksi yang tidak pernah ditutup atau kueri lambat yang menahan koneksi lebih lama dari seharusnya.

Solusi pertama yang muncul di hampir setiap forum adalah menaikkan `max_connections`. Itu memang menghilangkan pesan errornya, untuk sementara.

Masalahnya, batas itu ada dengan alasan. Setiap koneksi memakan memori, dan menaikkannya tanpa memeriksa apa yang mengisinya berarti menukar satu kegagalan dengan kegagalan lain yang lebih sulit dipulihkan.

Lihat dulu siapa yang memakai koneksinya

Sebelum mengubah konfigurasi, satu perintah menjawab hampir semuanya: `SHOW PROCESSLIST` — atau `SHOW FULL PROCESSLIST` supaya kueri tidak terpotong.

Yang dicari adalah pola. Banyak baris dengan status `Sleep` berarti koneksi terbuka tanpa mengerjakan apa pun. Banyak baris dengan kueri yang sama dan waktu berjalan tinggi berarti ada kueri lambat yang menumpuk. Baris dengan status `Locked` atau `Waiting for table metadata lock` berarti ada yang saling menunggu.

Ketiga pola itu punya perbaikan yang berbeda, dan itulah kenapa menaikkan batas tanpa melihat dulu adalah tembakan dalam gelap.

Proses sleep menumpuk: koneksi yang tidak ditutup

Kalau proses sleep menumpuk sampai puluhan atau ratusan, penyebabnya di sisi aplikasi: koneksi dibuka lalu tidak ditutup, dan basis data menahannya sampai batas waktu.

Periksa nilai `wait_timeout`. Bawaannya delapan jam, yang jauh terlalu lama untuk aplikasi web — koneksi yang ditinggalkan menganggur akan bertahan sepanjang hari kerja. Menurunkannya ke beberapa menit membersihkan koneksi mati jauh lebih cepat.

Tapi itu meredakan gejala. Perbaikan sebenarnya di kode: pastikan koneksi ditutup setelah dipakai, atau lebih baik lagi pakai connection pool aplikasi sehingga sejumlah kecil koneksi dipakai bergantian alih-alih dibuka baru setiap permintaan.

Kueri lambat menahan koneksi lebih lama

Pola kedua lebih halus. Ketika kueri lambat menahan koneksi, jumlah koneksi bersamaan naik bukan karena trafik bertambah, tetapi karena setiap permintaan bertahan lebih lama.

Hitungannya sederhana. Kalau satu permintaan memakai koneksi selama 50 milidetik, seratus permintaan per detik hanya butuh sekitar lima koneksi bersamaan. Kalau kuerinya melambat menjadi dua detik, jumlah yang sama butuh dua ratus koneksi — dan batasnya tersentuh tanpa ada perubahan trafik sama sekali.

Karena itu batas koneksi yang tercapai sering merupakan gejala performa, bukan gejala kapasitas. Memperbaiki kueri lambatnya menyelesaikan keduanya sekaligus.

Max connections mysql: menghitung batas yang wajar

Setelah penyebabnya ditangani, barulah pantas meninjau nilai max connections mysql. Angkanya tidak bisa ditebak — ia dibatasi memori.

Setiap koneksi memakai memori untuk buffer per-koneksi seperti `sort_buffer_size` dan `join_buffer_size`. Total memori MySQL kira-kira buffer global — terutama `innodb_buffer_pool_size` — ditambah jumlah koneksi dikali buffer per-koneksi.

Artinya menaikkan jumlah koneksi mengurangi memori yang tersedia untuk buffer pool, dan buffer pool yang mengecil membuat semua kueri lebih lambat. Ada titik di mana menaikkan batas justru memperburuk keadaan.

Praktik yang kami pakai: hitung kebutuhan koneksi dari jumlah worker aplikasi, bukan dari tebakan. Kalau ada tiga server aplikasi dengan lima puluh worker masing-masing, batas 200 sudah masuk akal; kalau satu server dengan dua puluh worker, 100 sudah longgar.

Kapan menaikkan max connections memang benar

Ada kondisi di mana menaikkan max connections adalah jawaban yang tepat, dan menahannya justru merugikan. Beberapa di antaranya:

  • Jumlah server aplikasi bertambah, sehingga kebutuhan koneksinya memang naik secara sah.
  • Batasnya masih pada nilai bawaan 151 padahal server punya memori besar dan beban nyata melampauinya.
  • Ada beberapa aplikasi berbeda berbagi satu basis data, masing-masing dengan pool sendiri.
  • Anda memakai proxy koneksi seperti ProxySQL yang memang membuka banyak koneksi ke belakang.
  • Sedang menangani lonjakan sementara dan butuh waktu untuk perbaikan yang benar — dengan catatan itu dicatat sebagai utang, bukan solusi.

Menyiapkan diri sebelum terjadi lagi

Kejadian ini punya sifat yang tidak menyenangkan: ketika batas tercapai, Anda juga tidak bisa masuk untuk memeriksanya. MySQL menyisakan satu koneksi untuk pengguna dengan hak `SUPER`, jadi pastikan ada akun administratif yang memilikinya — bukan hanya akun aplikasi.

Selain itu, pemantauan pada tiga angka ini memberi peringatan jauh sebelum batasnya tersentuh: jumlah koneksi aktif, `Threads_connected` dibanding `max_connections`, dan jumlah kueri lambat per menit.

Yang terakhir paling berguna sebagai peringatan dini. Kenaikan kueri lambat hampir selalu mendahului masalah koneksi, jadi ia memberi waktu bertindak sebelum ada yang mengeluh.

Menangani saat kejadian, tanpa memperburuk

Ketika batas sudah tercapai dan aplikasi mati, urutan tindakan berikut memulihkan layanan tanpa menghapus jejak penyebabnya.

Ada satu pola yang layak diwaspadai pada aplikasi modern: setiap instance aplikasi membuka pool koneksinya sendiri. Menambah satu container atau satu server aplikasi berarti menambah sekumpulan koneksi baru ke basis data, dan batasnya bisa tersentuh hanya karena penskalaan yang berhasil.

Karena itu ukuran pool perlu dihitung terhadap jumlah instance maksimum, bukan jumlah sekarang. Pada lingkungan yang menskalakan otomatis, ini termasuk hal pertama yang kami periksa.

  • Masuk dengan akun yang punya hak `SUPER` — koneksi cadangan yang disisakan MySQL memang untuk ini.
  • Jalankan `SHOW FULL PROCESSLIST` dan simpan keluarannya sebelum apa pun dihentikan.
  • Hentikan koneksi yang jelas menganggur lama dengan `KILL`, mulai dari yang statusnya `Sleep` dan waktunya paling besar.
  • Kalau ada satu kueri yang berjalan sangat lama dan menahan yang lain, hentikan itu juga — catat kuerinya untuk diperbaiki.
  • Turunkan `wait_timeout` untuk sesi berikutnya bila koneksi menganggur memang penyebabnya.
  • Setelah pulih, baru periksa log kueri lambat untuk penyebab yang sebenarnya.

Bacaan dan layanan terkait

FAQ

Pertanyaan terkait

Kenapa error ini muncul tiba-tiba padahal tidak ada perubahan?

Biasanya ada yang berubah tetapi bukan di konfigurasi — data bertambah sehingga kueri yang tadinya cepat menjadi lambat, dan koneksi tertahan lebih lama. Periksa kueri lambat sebelum konfigurasi.

Connection pool selalu lebih baik?

Untuk aplikasi dengan banyak permintaan singkat, ya, karena menghindari biaya membuka koneksi baru. Yang perlu diperhatikan: ukuran pool dikali jumlah instance aplikasi tidak boleh melampaui batas basis data.

Apakah restart MySQL menyelesaikannya?

Ia membersihkan semua koneksi sehingga layanan pulih sesaat, tapi kalau penyebabnya koneksi yang tidak ditutup atau kueri lambat, masalahnya kembali dalam hitungan jam.

Bagaimana di MariaDB?

Perilaku dan nama parameternya sama, jadi seluruh langkah di atas berlaku. MariaDB punya thread pool bawaan yang bisa membantu pada beban koneksi tinggi, dan itu layak dipertimbangkan.

Apakah proxy koneksi seperti ProxySQL menyelesaikan ini?

Bisa membantu, karena ia menyatukan banyak koneksi aplikasi menjadi sedikit koneksi ke basis data. Yang perlu diingat: ia menambah satu komponen yang harus dipantau dan bisa gagal.

Bagaimana kalau errornya muncul hanya saat cadangan berjalan?

Proses cadangan memang membuka koneksi dan bisa menahan tabel. Jadwalkan di jam paling sepi, dan untuk basis data besar pertimbangkan mencadangkan dari replika alih-alih dari server utama.

Berapa nilai wait_timeout yang wajar?

Untuk aplikasi web, beberapa menit biasanya cukup — jauh di bawah bawaannya. Yang perlu dihindari adalah menurunkannya terlalu agresif sehingga koneksi yang masih dipakai ikut terputus.

Apakah menambah memori server menyelesaikannya?

Ia memungkinkan batas koneksi dinaikkan lebih tinggi, jadi bisa membantu. Tetapi kalau penyebabnya koneksi yang tidak ditutup, jumlahnya akan terus bertambah sampai batas berapa pun tersentuh.

Apakah error ini bisa muncul di lingkungan pengujian?

Bisa, dan justru berguna kalau terjadi di sana. Lingkungan pengujian dengan batas koneksi yang disetel lebih rendah daripada produksi akan memperlihatkan kebocoran koneksi lebih awal, sebelum ia menjadi masalah di sistem yang dipakai pelanggan.

Ada bagian dari artikel ini yang ingin diterapkan?

Kalau salah satu langkah di atas relevan untuk sistem Anda tapi belum ada yang mengerjakannya, ceritakan kondisinya. Kami bantu petakan mana yang paling mendesak.

WhatsApp