MySQL Performance Schema Kullanım Rehberi

MySQL kurulumunuzda bir performans sorunu yaşıyorsunuz ama tam olarak nerede takıldığını bilmiyorsunuz. Yavaş sorgu logu var, EXPLAIN var, ama bunlar size yalnızca bir kısmını anlatıyor. İşte tam bu noktada Performance Schema devreye giriyor. MySQL 5.5 ile birlikte hayatımıza giren bu araç, veritabanı sunucunuzun içinde neler döndüğünü gerçek zamanlı olarak izlemenizi sağlayan düşük seviyeli bir izleme altyapısı. Doğru kullanıldığında, sorunları saatlerce debug etmek yerine dakikalar içinde tespit edebilirsiniz.

Performance Schema Nedir ve Nasıl Çalışır

Performance Schema, MySQL’in kendi içinde çalışan bir izleme motorudur. Normal bir veritabanı gibi davranır, yani SQL ile sorgularsınız, ama aslında disk üzerinde hiçbir şey yazmaz. Tüm veriler memory’de tutulur ve sunucu kapandığında sıfırlanır.

Temel çalışma prensibi enstrümantasyon (instrumentation) üzerine kuruludur. MySQL kaynak kodundaki belirli noktalara “probe” yerleştirilmiştir. Bu probe’lar etkinleştirildiğinde olay bilgilerini toplar, devre dışı bırakıldığında ise hiçbir overhead oluşturmaz. Bu mimarinin güzel tarafı, sadece ihtiyacınız olan şeyleri aktif edebilmenizdir.

Temel bileşenler şunlardır:

  • Instruments: Ölçüm yapılan kod noktaları. wait/io/file/sql/FRM gibi hiyerarşik bir isimlendirme sistemine sahiptir.
  • Consumers: Toplanan verilerin yazıldığı tablolar. events_waits_current, events_statements_history gibi.
  • Actors: Hangi kullanıcıların izleneceğini belirler.
  • Objects: Hangi tabloların veya schema’ların izleneceğini belirler.

Performance Schema’yı Aktif Etmek

MySQL 5.7 ve sonrasında Performance Schema varsayılan olarak açık gelir. Kontrol etmek için:

mysql -u root -p -e "SHOW VARIABLES LIKE 'performance_schema';"

Eğer kapalıysa, /etc/mysql/mysql.conf.d/mysqld.cnf veya /etc/my.cnf dosyasına şunu ekleyin:

[mysqld]
performance_schema = ON
performance_schema_events_statements_history_long_size = 10000
performance_schema_events_waits_history_long_size = 10000

Değişikliği uygulamak için MySQL’i yeniden başlatmanız gerekir:

systemctl restart mysql
# Sonra doğrulayın
mysql -u root -p -e "SELECT * FROM performance_schema.setup_instruments LIMIT 5;"

Hangi Instrument’ları Aktif Etmeli

Tüm instrument’ları aynı anda açmak istemezsiniz, gereksiz overhead yaratır. Temel sorgu analizi için şu setup’ı kullanabilirsiniz:

-- Statement izlemeyi aktif et
UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES', TIMED = 'YES' 
WHERE NAME LIKE 'statement/%';

-- Wait event'larını aktif et
UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES', TIMED = 'YES' 
WHERE NAME LIKE 'wait/%';

-- Consumer tabloları aktif et
UPDATE performance_schema.setup_consumers 
SET ENABLED = 'YES' 
WHERE NAME IN (
    'events_statements_current',
    'events_statements_history',
    'events_statements_history_long',
    'events_waits_current',
    'events_waits_history_long'
);

Gerçek Dünya Senaryosu 1: Yavaş Sorguları Tespit Etmek

Diyelim ki uygulamanız belli saatlerde yavaşlıyor ama yavaş sorgu logunda belirgin bir şey göremiyorsunuz. Performance Schema’nın events_statements_summary_by_digest tablosu burada altın değerinde.

-- En çok zaman harcayan sorguları bul
SELECT 
    DIGEST_TEXT,
    COUNT_STAR AS execution_count,
    ROUND(AVG_TIMER_WAIT / 1000000000, 3) AS avg_seconds,
    ROUND(MAX_TIMER_WAIT / 1000000000, 3) AS max_seconds,
    ROUND(SUM_TIMER_WAIT / 1000000000, 3) AS total_seconds,
    SUM_ROWS_EXAMINED AS total_rows_examined,
    SUM_ROWS_SENT AS total_rows_sent
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT IS NOT NULL
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;

Bu sorgu size en maliyetli 10 sorguyu getirecek. Burada dikkat etmeniz gereken önemli bir metrik, SUM_ROWS_EXAMINED ile SUM_ROWS_SENT arasındaki fark. Eğer bir sorgu 1.000.000 satır inceleyip yalnızca 10 satır döndürüyorsa, o sorguda ciddi bir index eksikliği var demektir.

Daha detaylı analiz için şu bash scriptini bir cron job olarak çalıştırabilirsiniz:

#!/bin/bash
# /usr/local/bin/mysql_perf_check.sh

MYSQL_USER="monitoring"
MYSQL_PASS="your_password"
LOG_FILE="/var/log/mysql_performance_$(date +%Y%m%d_%H%M).log"

mysql -u$MYSQL_USER -p$MYSQL_PASS performance_schema <<EOF > $LOG_FILE
SELECT 
    LEFT(DIGEST_TEXT, 100) AS query_snippet,
    COUNT_STAR,
    ROUND(AVG_TIMER_WAIT/1000000000, 4) AS avg_sec,
    ROUND(SUM_TIMER_WAIT/1000000000, 2) AS total_sec
FROM events_statements_summary_by_digest
WHERE AVG_TIMER_WAIT > 1000000000
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 20;
EOF

echo "Performance raporu: $LOG_FILE"

Gerçek Dünya Senaryosu 2: Lock Sorunlarını Bulmak

Uygulama loglarında zaman zaman “Lock wait timeout exceeded” hatası görüyorsunuz. Bunu Production’da yakalamak zor, ama Performance Schema bunu sizin için kayıt altına alıyor.

-- Aktif lock beklemelerini görüntüle
SELECT 
    r.trx_id AS waiting_trx_id,
    r.trx_mysql_thread_id AS waiting_thread,
    r.trx_query AS waiting_query,
    b.trx_id AS blocking_trx_id,
    b.trx_mysql_thread_id AS blocking_thread,
    b.trx_query AS blocking_query
FROM information_schema.innodb_lock_waits w
JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;

MySQL 8.0 kullanıyorsanız bu tablolar performance_schema altına taşındı:

-- MySQL 8.0 için lock analizi
SELECT 
    waiting_pid,
    waiting_query,
    blocking_pid,
    blocking_query,
    locked_table,
    locked_index,
    wait_age_secs
FROM sys.innodb_lock_waits;

Geçmiş Lock Event’larını Analiz Etmek

Anlık değil de geçmişe dönük lock sorunlarını araştırmak için:

SELECT 
    EVENT_NAME,
    SOURCE,
    TIMER_WAIT / 1000000000 AS wait_seconds,
    OBJECT_SCHEMA,
    OBJECT_NAME,
    INDEX_NAME,
    OPERATION,
    NESTING_EVENT_TYPE
FROM performance_schema.events_waits_history_long
WHERE EVENT_NAME LIKE '%lock%'
    AND TIMER_WAIT > 1000000000
ORDER BY TIMER_WAIT DESC
LIMIT 20;

sys Schema ile Performance Schema’yı Daha Kolay Kullanmak

MySQL 5.7.7 ve sonrasında gelen sys schema, Performance Schema üzerine kurulu view’lar ve stored procedure’lar içerir. Ham tabloları ezberlemenize gerek kalmaz, çok daha okunabilir sorgular yazabilirsiniz.

-- En çok I/O yapan tablolar
SELECT * FROM sys.io_global_by_file_by_bytes LIMIT 10;

-- En çok kullanılan index'ler
SELECT * FROM sys.schema_index_statistics 
ORDER BY rows_selected DESC 
LIMIT 10;

-- Hiç kullanılmayan index'ler (bunları silebilirsiniz!)
SELECT * FROM sys.schema_unused_indexes 
WHERE object_schema NOT IN ('mysql', 'sys', 'information_schema', 'performance_schema');

Kullanılmayan index’leri bulmak Production DBA’lerinin en çok işine yarayan sorgulardan biridir. Gereksiz index’ler disk alanı tüketir ve INSERT/UPDATE işlemlerini yavaşlatır. Bu sorguyu çalıştırmadan önce sisteminizin en az birkaç gün boyunca normal yük altında çalışmış olmasına dikkat edin.

Gerçek Dünya Senaryosu 3: Memory Kullanımını İzlemek

Bir production sunucusunda MySQL belleği beklenmedik şekilde artıyorsa, memory instrument’larını aktif edip analiz edebilirsiniz:

# Memory instrument'larını aktif et
mysql -u root -p <<'EOF'
UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES' 
WHERE NAME LIKE 'memory/%';
EOF

Ardından bellek kullanımını analiz edin:

-- En çok bellek tüketen bileşenler
SELECT 
    EVENT_NAME,
    CURRENT_COUNT_USED AS current_allocations,
    ROUND(CURRENT_NUMBER_OF_BYTES_USED / 1024 / 1024, 2) AS current_mb,
    ROUND(HIGH_NUMBER_OF_BYTES_USED / 1024 / 1024, 2) AS peak_mb
FROM performance_schema.memory_summary_global_by_event_name
WHERE CURRENT_NUMBER_OF_BYTES_USED > 0
ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC
LIMIT 15;

Eğer memory/innodb/buf_pool kalemi beklenenden fazlaysa, innodb_buffer_pool_size ayarınızı gözden geçirmeniz gerekiyor. Genellikle bu değer sunucu RAM’inin %60-70’i olarak ayarlanır, ama workload’unuza göre fine-tune etmeniz gerekir.

Kullanıcı Bazlı Performans Analizi

Birden fazla uygulama veya ekibin aynı MySQL sunucusunu kullandığı ortamlarda, kimin ne kadar kaynak tükettiğini bilmek kritik önem taşır:

-- Kullanıcı bazlı kaynak tüketimi
SELECT 
    USER,
    COUNT_STAR AS total_queries,
    ROUND(SUM_TIMER_WAIT / 1000000000 / 60, 2) AS total_minutes,
    ROUND(AVG_TIMER_WAIT / 1000000000, 4) AS avg_seconds,
    SUM_ERRORS AS total_errors,
    SUM_ROWS_EXAMINED AS rows_examined,
    SUM_ROWS_SENT AS rows_sent,
    SUM_SELECT_FULL_JOIN AS full_joins,
    SUM_SELECT_SCAN AS full_scans
FROM performance_schema.events_statements_summary_by_user_by_event_name
WHERE EVENT_NAME = 'statement/sql/select'
    AND COUNT_STAR > 0
ORDER BY SUM_TIMER_WAIT DESC;

SUM_SELECT_FULL_JOIN ve SUM_SELECT_SCAN değerlerine özellikle dikkat edin. Full join ve full scan sayısı yüksekse, o kullanıcının sorguları ciddi performans sorunlarına yol açıyor olabilir.

Replication Gecikmesini Performance Schema ile İzlemek

Master-slave replikasyon kurulumlarında gecikme sorunları sık karşılaşılan problemlerden biridir. Standart SHOW SLAVE STATUS çıktısı bazen yeterli detay vermez:

-- Replication worker thread performansı (MySQL 5.7+)
SELECT 
    CHANNEL_NAME,
    THREAD_ID,
    SERVICE_STATE,
    LAST_ERROR_NUMBER,
    LAST_ERROR_MESSAGE,
    LAST_PROCESSED_TRANSACTION
FROM performance_schema.replication_applier_status_by_worker;

-- Apply edilen transaction gecikmesi
SELECT 
    CHANNEL_NAME,
    LAST_APPLIED_TRANSACTION,
    APPLYING_TRANSACTION,
    LAST_APPLIED_TRANSACTION_ORIGINAL_COMMIT_TIMESTAMP,
    LAST_APPLIED_TRANSACTION_IMMEDIATE_COMMIT_TIMESTAMP
FROM performance_schema.replication_applier_status_by_worker;

Performance Schema Overhead’ini Minimize Etmek

“Performance Schema açıkken sunucum yavaşlar mı?” diye soruyorsanız, cevap “bağlıdır” şeklindedir. Tüm instrument’ları açarsanız evet, belirgin bir overhead olur. Ama seçici davranırsanız bu etki ihmal edilebilir düzeyde kalır.

Overhead’i azaltmak için öneriler:

  • Sadece ihtiyacınız olan instrument’ları aktif edin: Statement ve wait instrument’larını her zaman açık tutabilirsiniz, ama stage instrument’ları daha yüksek overhead yaratır.
  • History boyutlarını makul tutun: performance_schema_events_statements_history_long_size değerini gereğinden fazla büyütmeyin. 10.000 genellikle yeterlidir.
  • Aktif kullanmadığınızda bazı consumer’ları kapatın: Özellikle events_stages_history_long gibi ayrıntılı consumer’ları sadece debug sırasında açın.
# Belirli bir oturum için stage monitoring'i aktif et, işi bitince kapat
mysql -u root -p <<'EOF'
-- Aktif et
UPDATE performance_schema.setup_consumers 
SET ENABLED = 'YES' 
WHERE NAME = 'events_stages_current';

-- Analizini yap...

-- Kapat
UPDATE performance_schema.setup_consumers 
SET ENABLED = 'NO' 
WHERE NAME = 'events_stages_current';
EOF

İstatistikleri Sıfırlamak

Performance Schema verileri sunucu yeniden başlayana kadar birikmekte devam eder. Bazı durumlarda temiz bir başlangıç noktası oluşturmak istersiniz:

-- Tüm statement istatistiklerini sıfırla
TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;

-- Tüm özet tabloları tek seferde sıfırla
CALL sys.ps_truncate_all_tables(FALSE);
-- TRUE geçerseniz çıktı gösterir, FALSE sessiz çalışır

Bunu maintenance window’ları öncesinde veya büyük uygulama deployment’larından önce yaparak, yeni versiyonun performance profilini temiz bir şekilde analiz edebilirsiniz.

Monitoring Entegrasyonu

Performance Schema verilerini Prometheus veya Grafana gibi araçlara beslemek istiyorsanız, mysqld_exporter tam aradığınız şeydir:

# mysqld_exporter kurulumu (Ubuntu/Debian)
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.0/mysqld_exporter-0.15.0.linux-amd64.tar.gz
tar xvzf mysqld_exporter-0.15.0.linux-amd64.tar.gz
mv mysqld_exporter-0.15.0.linux-amd64/mysqld_exporter /usr/local/bin/

# Monitoring kullanıcısı oluştur
mysql -u root -p <<'EOF'
CREATE USER 'mysqld_exporter'@'localhost' 
    IDENTIFIED BY 'guclu_bir_sifre' 
    WITH MAX_USER_CONNECTIONS 3;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* 
    TO 'mysqld_exporter'@'localhost';
FLUSH PRIVILEGES;
EOF

# Credentials dosyası oluştur
cat > /etc/.mysqld_exporter.cnf <<'EOF'
[client]
user=mysqld_exporter
password=guclu_bir_sifre
EOF

chmod 600 /etc/.mysqld_exporter.cnf

mysqld_exporter, Performance Schema tablolarından veri çekip Prometheus formatında expose eder. Grafana üzerinde MySQL dashboard’ları kurduğunuzda, yavaş sorgulardan memory kullanımına, replication lag’dan connection pool doluluk oranına kadar her şeyi tek ekranda görebilirsiniz.

Dikkat Edilmesi Gereken Yaygın Hatalar

instrument ve consumer karıştırmak: Bir instrument’ı aktif etmek, verinin tablolara yazılacağı anlamına gelmez. İlgili consumer’ı da aktif etmeniz gerekir. Veri göremiyorsanız önce consumer’ları kontrol edin.

Production’da aniden tüm monitoring’i açmak: Yoğun saatlerde tüm instrument’ları açmak sisteminizi etkileyebilir. Bunu maintenance window’unda veya test ortamında deneyin, neye ihtiyacınız olduğuna karar verin, sonra production’a seçici biçimde uygulayın.

Verilerin geçici olduğunu unutmak: Performance Schema verileri RAM’de tutulur. Sunucu restart olduğunda her şey sıfırlanır. Uzun vadeli trend analizi için verileri periyodik olarak başka bir tabloya veya dosyaya kaydetmeniz gerekir.

sys schema ile Performance Schema tablolarını karıştırmak: sys schema view’ları çok daha okunabilir ama bazı durumlarda ham tablolara gitmek daha doğru sonuç verir. sys view’larının altında hangi tabloların yattığını anlamak için SHOW CREATE VIEW sys.statement_analysis; gibi komutlarla view tanımlarına bakabilirsiniz.

Sonuç

Performance Schema, MySQL’in içine yerleştirilmiş ve çoğu DBA’in tam olarak değerlendirmediği bir güç kaynağı. Yavaş sorgu logu reaktif bir araçken, Performance Schema size proaktif bir bakış açısı sunar. Hangi sorgular en fazla kaynak tüketiyor, hangi tablolar en çok lock bekliyor, hangi kullanıcılar sistemi zorluyor, bellek nereye akıyor? Bunların hepsine yanıt verebilir.

Başlangıç için şu yaklaşımı öneririm: önce sys schema view’larıyla tanışın, işleri basit tutun. Bir sorunla karşılaştığınızda sys.statement_analysis ve sys.innodb_lock_waits ile başlayın. Daha derin analiz gerektiğinde ham Performance Schema tablolarına inin. Monitoring altyapınız için mysqld_exporter ve Grafana kombinasyonunu kurun, böylece sorunları reactive değil proactive olarak yakalayın.

Veritabanı performansı yönetimi, tahmine değil veriye dayalı karar verme üzerine kurulmalıdır. Performance Schema tam da bunu sağlar.

Yorum yapın