Merhaba arkadaşlar, bugün sizlere özellikle MySQL/MariaDB sunucularınızda can sıkıcı bir durum olan, kaynakları tüketen kötü niyetli veya optimize edilmemiş sorguları nasıl tespit edip, nasıl durduracağınızı (kill/revoke) anlatacağım. Bu işlem, sunucunuzun anlık olarak nefes almasını sağlayacak ve uzun vadeli optimizasyon için size kritik veriler sunacaktır.
Kötü Sorguları Nasıl Tespit Ederiz?
Öncelikle hangi sorguların problem çıkardığını bulmamız lazım. MySQL/MariaDB'ye bağlanıp aşağıdaki komutu çalıştıralım. Bu komut, şu anda çalışan ve belirli bir süreyi geçmiş sorguları bize listeler.
Bu liste bazen çok uzun olabilir. Daha pratik bir yaklaşım olarak, `information_schema` üzerinden çalışan uzun süreli sorguları sıralayalım. Benim genelde kullandığım sorgu şudur:
Bu sorgu, 60 saniyeden uzun süredir çalışan ilk 10 sorguyu getirir. TIME sütununa çok dikkat etmelisiniz, çok yüksek değerler (300-500 saniye) genelde bir sorunun göstergesidir. Info sütunu ise sorgunun ilk 200 karakterini gösterir, ne yapmaya çalıştığını anlamanıza yardımcı olur.
Kritik Bir Uyarı
Burada çok önemli bir nokta var: Gördüğünüz her uzun süreli sorgu hemen kötü niyetli değildir! Örneğin, büyük bir raporlama sorgusu, yedekleme işlemi veya uzun süren bir veri temizleme işi olabilir. Sorguyu durdurmadan önce, Info alanına bakıp ne yaptığını anlamaya çalışın veya ilgili uygulama tarafındaki geliştiriciye danışın. Yanlış bir sorguyu durdurmak, veri bütünlüğünü bozabilir veya transaction kayıplarına yol açabilir.
Sorguyu Durdurma (KILL) Adımı
Eğer bir sorgunun kötü niyetli olduğundan, bir döngüye girdiğinden veya sistemi kilitlediğinden eminseniz, onu durdurma zamanı geldi demektir. Bunun için KILL komutunu kullanacağız.
İlk adımda tespit ettiğimiz sorgunun id değerini alıyoruz. Daha sonra aşağıdaki komutu çalıştırıyoruz:
Örneğin, ID'si 12345 olan bir sorguyu durdurmak için:
Bu işlem, sorguyu anında sonlandıracaktır. Bazen sorgu çok derinde kilitlenmiş olabilir ve KILL komutu hemen etki etmeyebilir. Bu durumda daha güçlü bir sinyal göndermek için KILL QUERY yerine doğrudan bağlantıyı sonlandıran KILL CONNECTION komutunu kullanabilirsiniz. Aslında standart `KILL`, `KILL CONNECTION` ile aynı işi yapar.
Proaktif Koruma ve İzleme
Sürekli manuel kontrol etmek yerine, bu tür sorunları proaktif olarak izleyebilir ve hatta otomatik engelleyebilirsiniz. Bunun için birkaç yöntem var:
1. Percona Toolkit veya pt-kill: Bu harika araç, belirlediğiniz kurallara (süre, kullanıcı, sorgu tipi) göre otomatik olarak sorguları sonlandırabilir. Kurulumu ayrı bir rehber konusu ama kullanımı şöyledir:
Bu komut, 120 saniyeden uzun süren SELECT veya UPDATE sorgularını bulur ve sonlandırır.
2. MySQL Event Scheduler: Basit bir stored procedure ve event ile belirli aralıklarla kontrol yapabilirsiniz.
3. Monitoring Sistemleri (Prometheus + Grafana): MySQL Exporter ile `processlist` ve uzun süren sorguları grafiklerde izleyip, belirli bir eşiği aşınca size uyarı (alert) göndermesini sağlayabilirsiniz. Bu, sorunu engellemeden önce tespit etmek için altın değerindedir.
En önemli dosya ve logları takip etmeyi unutmayın. Uzun sorguların detaylarını ve kill işlemlerini /var/log/mysql/error.log veya yavaş sorgu log'unda (slow_query_log_file) inceleyebilirsiniz.
Sonuç ve Tavsiyeler
Bu yöntem, acil durum müdahalesi için hayat kurtarıcıdır. Ancak asıl hedef, bu kötü sorguların neden oluştuğunu bulmaktır. Eksik indexler, optimize edilmemiş sorgular veya uygulama katmanındaki hatalar olabilir. `EXPLAIN` komutu ile sorguları analiz etmeyi ve gerekli indexlemeleri yapmayı ihmal etmeyin.
Siz bu tarz kötü sorgu problemleriyle karşılaştığınızda nasıl bir yol izliyorsunuz? Percona Toolkit veya farklı bir otomasyon aracı kullanıyor musunuz? Tecrübelerinizi ve sorularınızı aşağıya yazmaktan çekinmeyin, beraber öğrenelim.
Öncelikle hangi sorguların problem çıkardığını bulmamız lazım. MySQL/MariaDB'ye bağlanıp aşağıdaki komutu çalıştıralım. Bu komut, şu anda çalışan ve belirli bir süreyi geçmiş sorguları bize listeler.
SQL:
SHOW FULL PROCESSLIST;
Bu liste bazen çok uzun olabilir. Daha pratik bir yaklaşım olarak, `information_schema` üzerinden çalışan uzun süreli sorguları sıralayalım. Benim genelde kullandığım sorgu şudur:
SQL:
SELECT id, USER, HOST, db, COMMAND, TIME, STATE, LEFT(INFO, 200) AS Info
FROM information_schema.PROCESSLIST
WHERE COMMAND = 'Query'
AND TIME > 60
ORDER BY TIME DESC
LIMIT 10;
Bu sorgu, 60 saniyeden uzun süredir çalışan ilk 10 sorguyu getirir. TIME sütununa çok dikkat etmelisiniz, çok yüksek değerler (300-500 saniye) genelde bir sorunun göstergesidir. Info sütunu ise sorgunun ilk 200 karakterini gösterir, ne yapmaya çalıştığını anlamanıza yardımcı olur.
Burada çok önemli bir nokta var: Gördüğünüz her uzun süreli sorgu hemen kötü niyetli değildir! Örneğin, büyük bir raporlama sorgusu, yedekleme işlemi veya uzun süren bir veri temizleme işi olabilir. Sorguyu durdurmadan önce, Info alanına bakıp ne yaptığını anlamaya çalışın veya ilgili uygulama tarafındaki geliştiriciye danışın. Yanlış bir sorguyu durdurmak, veri bütünlüğünü bozabilir veya transaction kayıplarına yol açabilir.
Eğer bir sorgunun kötü niyetli olduğundan, bir döngüye girdiğinden veya sistemi kilitlediğinden eminseniz, onu durdurma zamanı geldi demektir. Bunun için KILL komutunu kullanacağız.
İlk adımda tespit ettiğimiz sorgunun id değerini alıyoruz. Daha sonra aşağıdaki komutu çalıştırıyoruz:
SQL:
KILL [SORGUNUN_ID_DEGERI];
Örneğin, ID'si 12345 olan bir sorguyu durdurmak için:
SQL:
KILL 12345;
Bu işlem, sorguyu anında sonlandıracaktır. Bazen sorgu çok derinde kilitlenmiş olabilir ve KILL komutu hemen etki etmeyebilir. Bu durumda daha güçlü bir sinyal göndermek için KILL QUERY yerine doğrudan bağlantıyı sonlandıran KILL CONNECTION komutunu kullanabilirsiniz. Aslında standart `KILL`, `KILL CONNECTION` ile aynı işi yapar.
Sürekli manuel kontrol etmek yerine, bu tür sorunları proaktif olarak izleyebilir ve hatta otomatik engelleyebilirsiniz. Bunun için birkaç yöntem var:
1. Percona Toolkit veya pt-kill: Bu harika araç, belirlediğiniz kurallara (süre, kullanıcı, sorgu tipi) göre otomatik olarak sorguları sonlandırabilir. Kurulumu ayrı bir rehber konusu ama kullanımı şöyledir:
Bash:
pt-kill --host=localhost --user=monitor --password=XXX --match-info="SELECT|UPDATE" --busy-time 120 --kill --print
2. MySQL Event Scheduler: Basit bir stored procedure ve event ile belirli aralıklarla kontrol yapabilirsiniz.
3. Monitoring Sistemleri (Prometheus + Grafana): MySQL Exporter ile `processlist` ve uzun süren sorguları grafiklerde izleyip, belirli bir eşiği aşınca size uyarı (alert) göndermesini sağlayabilirsiniz. Bu, sorunu engellemeden önce tespit etmek için altın değerindedir.
En önemli dosya ve logları takip etmeyi unutmayın. Uzun sorguların detaylarını ve kill işlemlerini /var/log/mysql/error.log veya yavaş sorgu log'unda (slow_query_log_file) inceleyebilirsiniz.
Bu yöntem, acil durum müdahalesi için hayat kurtarıcıdır. Ancak asıl hedef, bu kötü sorguların neden oluştuğunu bulmaktır. Eksik indexler, optimize edilmemiş sorgular veya uygulama katmanındaki hatalar olabilir. `EXPLAIN` komutu ile sorguları analiz etmeyi ve gerekli indexlemeleri yapmayı ihmal etmeyin.
Siz bu tarz kötü sorgu problemleriyle karşılaştığınızda nasıl bir yol izliyorsunuz? Percona Toolkit veya farklı bir otomasyon aracı kullanıyor musunuz? Tecrübelerinizi ve sorularınızı aşağıya yazmaktan çekinmeyin, beraber öğrenelim.