Yirmi milyon satırlık bir tabloya yeni bir sütun eklemen gerekiyor. Düz ALTER TABLE yazarsan MySQL tabloyu yeniden inşa ederken uygulama o tabloya yazamaz ve sitede dakikalarca süren bir donma yaşanır. Ya da replikan master ile aynı veriye sahip mi, gerçekten emin misin? Percona Toolkit ile veritabanı bakımı tam olarak bu tür soruların cevabıdır: üretim ortamında, kesinti yaratmadan, ölçülebilir biçimde iş yapan komut satırı araçlarından oluşan bir set.
Bu rehberde Percona Toolkit'i kuracak ve günlük işlerde gerçekten kullanacağın altı aracı sırayla ele alacağız: pt-online-schema-change ile kilitsiz şema değişikliği, pt-table-checksum ve pt-table-sync ile replika tutarlılığı, pt-query-digest ile yavaş sorgu analizi, pt-archiver ile eski kayıtları güvenle temizleme, pt-kill ile kaçak sorguları durdurma ve pt-mysql-summary ile hızlı durum raporu. Her aracın hangi durumda gerçekten işe yaradığını ve nerede tehlikeli olduğunu ayrı ayrı işaretleyeceğim, çünkü bu araçların bazıları veri üzerinde geri dönüşü olmayan işlemler yapar.
Percona Toolkit Kurulumu#
Percona Toolkit, Perl ile yazılmış bağımsız betiklerden oluşur; MySQL sunucusuna kurulum yapmaz, yalnızca ona bağlanır. Bu yüzden araçları veritabanı sunucusunda değil, ayrı bir yönetim makinesinde de çalıştırabilirsin. Debian ve Ubuntu'da en temiz kurulum üreticinin kendi deposu üzerinden yapılır.
# Percona deposunu ekle
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb
sudo dpkg -i percona-release_latest.generic_all.deb
sudo percona-release setup ps80
sudo apt update
sudo apt install -y percona-toolkit
# Kurulumu doğrula
pt-online-schema-change --version
Araçların hepsi aynı bağlantı seçeneklerini kullanır: --host, --port, --user, --password, --socket. Parolayı komut satırına yazmak süreç listesinde görünmesine yol açtığı için, kalıcı kullanımda bir seçenek dosyası oluşturmak çok daha güvenlidir:
# ~/.my.cnf — sadece kendi kullanıcın okuyabilsin: chmod 600 ~/.my.cnf
[client]
user=bakim
password=GucluBirParola
host=127.0.0.1
port=3306
Bakım kullanıcısına gereğinden fazla yetki verme; her aracın ihtiyaç duyduğu yetkiler farklıdır ve çoğu için SELECT, PROCESS, REPLICATION CLIENT ve ilgili tablolar üzerinde ALTER yeterlidir. Yetkileri daraltmak istiyorsan MySQL kullanıcı ve yetki yönetimi yazısındaki nesne bazlı GRANT örnekleri işini görür. Araçların hangi işe yaradığına kuşbakışı bakalım:
| Araç | Ne yapar | Risk seviyesi |
|---|---|---|
| pt-online-schema-change | Tabloyu kilitlemeden ALTER uygular | Orta — tetikleyici oluşturur |
| pt-table-checksum | Master ve replika verisini karşılaştırır | Düşük — yalnızca okur |
| pt-table-sync | Replikadaki farkları düzeltir | Yüksek — veri değiştirir |
| pt-query-digest | Yavaş sorgu günlüğünü raporlar | Yok — dosya okur |
| pt-archiver | Eski satırları taşır veya siler | Yüksek — veri siler |
| pt-kill | Uzun süren sorguları sonlandırır | Orta — işlem keser |
| pt-mysql-summary | Sunucu durumunu özetler | Yok |
pt-online-schema-change ile Kilitlemeden Şema Değiştirme#
Bu araç, toolkit'in en çok kullanılan parçasıdır ve mantığı zekicedir. Doğrudan tabloyu değiştirmek yerine, hedef tablonun yeni şemaya sahip boş bir kopyasını oluşturur, orijinal tabloya üç tetikleyici (INSERT, UPDATE, DELETE) ekler ki değişiklikler yeni tabloya da yansısın, ardından eski satırları parça parça kopyalar. Kopyalama bittiğinde iki tabloyu atomik olarak takas eder ve tetikleyicileri siler. Uygulama bu sürecin tamamında yazmaya devam eder.
Her zaman önce prova çalıştır. --dry-run hiçbir şeyi değiştirmez, yalnızca ne yapacağını anlatır:
pt-online-schema-change \
--alter "ADD COLUMN son_giris_at DATETIME NULL" \
D=magaza,t=musteriler \
--dry-run
Çıktı beklediğin gibiyse --execute ile gerçek çalıştırmayı yap. Üretimde mutlaka yük koruma parametrelerini de ekle:
pt-online-schema-change \
--alter "ADD COLUMN son_giris_at DATETIME NULL" \
D=magaza,t=musteriler \
--chunk-size=1000 \
--max-load="Threads_running=40" \
--critical-load="Threads_running=100" \
--max-lag=5 \
--check-interval=2 \
--execute
Bu parametrelerin her biri bir güvenlik supabıdır. --max-load eşiği aşıldığında araç kopyalamayı duraklatır ve yük düşünce devam eder; --critical-load aşıldığında ise tamamen durur. --max-lag replikasyon gecikmesi belirtilen saniyeyi geçtiğinde bekler, böylece bakım işlemi replikaları geride bırakmaz. --chunk-size her turda kaç satır kopyalanacağını belirler; küçük tutmak işlemi uzatır ama sunucuyu rahatlatır.
İki önemli uyarı var. Birincisi, tabloda birincil anahtar ya da benzersiz indeks bulunmak zorundadır; yoksa araç çalışmayı reddeder. İkincisi, hedef tabloya başka tablolardan yabancı anahtar (foreign key) bakıyorsa --alter-foreign-keys-method seçeneğini bilinçli olarak belirtmen gerekir. rebuild_constraints genellikle en güvenli seçenektir ama ilgili tabloları da yeniden inşa ettiği için uzun sürebilir. Araç ayrıca disk alanı ister: işlem sırasında tablonun iki kopyası aynı anda diskte durur, bu yüzden başlamadan önce boş alanı kontrol et.
pt-table-checksum ile Replika Tutarlılığını Doğrulamak#
Replikasyonun "çalışıyor" görünmesi, verinin aynı olduğu anlamına gelmez. Seconds_Behind_Master sıfır olsa bile, geçmişte replikada elle yapılmış bir yazma ya da atlanan bir hata yüzünden satırlar sessizce farklılaşmış olabilir. pt-table-checksum bunu ölçen tek pratik araçtır.
Çalışma mantığı şudur: master üzerinde tabloları parçalara böler, her parçanın sağlama toplamını hesaplar ve bu hesaplamayı replikasyon üzerinden replikalara gönderir. Replika aynı hesabı kendi verisiyle yapar; sonuçlar farklıysa o parça işaretlenir.
pt-table-checksum \
--host=185.12.34.51 --user=bakim --ask-pass \
--databases=magaza \
--replicate=percona.checksums \
--no-check-binlog-format
Aracın çalışması için binlog formatının uygun olması ve replikaların master üzerinden keşfedilebilmesi gerekir. Sonuçları sonradan sorgulamak için replika üzerinde şu sorguyu çalıştırırsın:
SELECT db, tbl, chunk, this_crc, master_crc, this_cnt, master_cnt
FROM percona.checksums
WHERE this_crc != master_crc OR this_cnt != master_cnt;
Bu sorgu satır döndürüyorsa gerçek bir tutarsızlık var demektir. Düzeltmek için pt-table-sync kullanılır ve burada çok dikkatli olman gerekir; bu araç veri yazar.
# ÖNCE ne yapacağını gör — hiçbir şey değiştirmez
pt-table-sync --print --replicate=percona.checksums \
--sync-to-master h=185.12.34.52,u=bakim,p=Parola
# Çıktıyı inceledikten SONRA uygula
pt-table-sync --execute --replicate=percona.checksums \
--sync-to-master h=185.12.34.52,u=bakim,p=Parola
--sync-to-master seçeneği master'ı doğru kaynak kabul eder ve yalnızca replikayı düzeltir. Bu seçeneği unutup yanlış yönde senkronizasyon başlatmak, master'daki doğru veriyi bozabilir. Kural basit: --execute yazmadan önce mutlaka --print çıktısını oku. Replikasyonun kendisini nasıl kuracağını hatırlaman gerekirse MySQL replikasyon kurulumu yazısı temel yapılandırmayı anlatıyor.
pt-query-digest ile Yavaş Sorgu Analizi#
MySQL'in yavaş sorgu günlüğü ham hâliyle okunması zor bir dosyadır; binlerce satır içinde hangi sorgunun toplam yükün ne kadarını oluşturduğunu görmek neredeyse imkânsızdır. pt-query-digest bu dosyayı okuyup sorguları normalleştirir, aynı desendeki sorguları gruplar ve toplam süreye göre sıralar.
pt-query-digest /var/log/mysql/mysql-slow.log --limit=10
Çıktının başındaki profil bölümü, işin özünü verir:
# Profile
# Rank Query ID Response time Calls R/Call Item
# ==== ================== =============== ====== ======= ==============
# 1 0x8F1B2C3D4E5A6B7 842.1194 61.3% 1204 0.6994 SELECT siparis
# 2 0x1A2B3C4D5E6F7A8 212.4451 15.5% 84120 0.0025 SELECT urun
# 3 0x9F8E7D6C5B4A392 98.7710 7.2% 36 2.7436 SELECT rapor
Bu tablo bir şeyi çok net gösterir: en yavaş sorgu ile en çok yük üreten sorgu farklı şeylerdir. Üçüncü sıradaki sorgu çağrı başına 2,7 saniye sürüyor ama günde yalnızca 36 kez çalıştığı için toplam etkisi düşük. İkinci sıradaki sorgu ise 2,5 milisaniyede bitiyor ama 84 bin kez çağrıldığı için toplam yükün yüzde 15'ini tek başına üretiyor. Optimizasyona daima toplam süreye göre başla.
Belirli bir zaman aralığını incelemek ya da yalnızca belli bir kullanıcının sorgularına bakmak da mümkündür:
# Yalnızca son bir saatlik dilim
pt-query-digest --since '1h' /var/log/mysql/mysql-slow.log
# Yalnızca belirli bir veritabanı
pt-query-digest --filter '$event->{db} && $event->{db} eq "magaza"' \
/var/log/mysql/mysql-slow.log
Yavaş sorgu günlüğü kapalıysa bu aracın okuyacağı bir şey olmaz; günlüğü doğru eşiklerle açmak için slow query log yapılandırma yazısındaki ayarları uygula. Günlüğe hiç dokunmadan canlı trafiği incelemek istersen tcpdump çıktısını da besleyebilirsin, ancak bu yöntem sunucuya ek yük bindirir ve yalnızca kısa örnekleme için uygundur.
pt-archiver ile Eski Kayıtları Güvenle Temizlemek#
Log, oturum ve bildirim tabloları büyümeye devam eder ve bir gün tek bir DELETE FROM ... WHERE tarih < ... ifadesi yazmak istersin. Bunu yapma. Milyonlarca satırı tek işlemde silmek InnoDB'de devasa bir geri alma (undo) alanı üretir, tabloyu uzun süre kilitler ve replikaları dakikalarca geride bırakır. pt-archiver aynı işi küçük parçalar hâlinde, aralarda nefes alarak yapar.
Kayıtları başka bir tabloya taşıyarak arşivlemek:
pt-archiver \
--source h=127.0.0.1,D=magaza,t=islem_log \
--dest h=127.0.0.1,D=arsiv,t=islem_log \
--where "olusturma < NOW() - INTERVAL 180 DAY" \
--limit=1000 --commit-each \
--sleep=1 --statistics
Yalnızca silmek istiyorsan hedef belirtmezsin ama --purge seçeneğini açıkça yazman gerekir:
pt-archiver \
--source h=127.0.0.1,D=magaza,t=oturum \
--where "son_erisim < NOW() - INTERVAL 30 DAY" \
--limit=2000 --commit-each --sleep=1 \
--purge --statistics
Buradaki --sleep=1 parametresi, her parti arasında bir saniye beklemesini söyler ve replikasyon gecikmesini önlemenin en basit yoludur. --limit parti büyüklüğüdür; --commit-each her partiyi ayrı işlem olarak kaydeder, böylece uzun süren tek bir transaction oluşmaz. --statistics ise sonunda kaç satır işlendiğini ve ne kadar sürdüğünü raporlar. Bu komutları ilk kez çalıştırırken --dry-run ekleyip ne yapacağını görmeni, ayrıca öncesinde mutlaka yedek almanı öneririm; mysqldump ile veritabanı yedekleme küçük tablolar için hızlı bir güvenlik ağıdır.
pt-kill, pt-mysql-summary ve Günlük Kontroller#
Bazen bir raporlama sorgusu kontrolden çıkar ve dakikalarca çalışarak sunucuyu boğar. pt-kill, belirlediğin ölçütlere uyan sorguları bulup sonlandırır. İlk çalıştırmada daima --print kullan; ne öldüreceğini görmeden --kill yazma.
# 60 saniyeden uzun süren SELECT'leri sadece listele
pt-kill --busy-time 60 --match-command Query --match-info "^SELECT" --print
# İkna olduktan sonra öldürmeye başla, sürekli çalışsın
pt-kill --busy-time 120 --match-command Query --match-info "^SELECT" \
--interval 10 --kill --daemonize --log /var/log/pt-kill.log
--match-command Query filtresi önemlidir; onsuz uyku durumundaki bağlantıları ya da replikasyon iş parçacıklarını da yakalayabilirsin. Yazma sorgularını asla otomatik öldürme; yarım kalan bir yazmanın geri alınması, sorgunun kendisinden daha uzun sürebilir.
Bir sunucuya ilk kez baktığında ya da bir sorunu raporlarken pt-mysql-summary çıktısı çok işine yarar. Sürüm, yapılandırma, tablo motorları, tampon havuzu boyutu, bağlantı sayıları ve replikasyon durumunu tek sayfada toplar:
pt-mysql-summary --user=bakim --ask-pass > /tmp/db-ozet.txt
# İşletim sistemi tarafı için
pt-summary > /tmp/os-ozet.txt
Bu iki dosya, bir performans sorununu tarif etmenin en hızlı yoludur. Tampon havuzu ve bağlantı ayarlarını yorumlarken MySQL ve MariaDB performans optimizasyonu yazısındaki eşik değerleri karşılaştırma için elinin altında dursun.
Sık Yapılan Hatalar ve Dikkat Edilecekler#
Birincisi ve en pahalısı, --execute parametresini prova yapmadan kullanmaktır. pt-table-sync ve pt-archiver veri değiştirir; yanlış bir --where ifadesi ya da eksik bir --sync-to-master seçeneği geri alınamaz kayıplara yol açar. Bu iki aracı çalıştırmadan önce güncel bir yedeğin olduğundan emin ol.
İkincisi, pt-online-schema-change çalışırken tabloda zaten tetikleyici bulunmasıdır. Araç kendi tetikleyicilerini ekleyemez ve durur. Eski MySQL sürümlerinde tablo başına tek tetikleyici sınırı vardı; modern sürümlerde bu kalksa da, uygulamanın kendi tetikleyicileriyle aracınkilerin etkileşimini düşünmelisin. Aynı şekilde, araç yarıda kesilirse _tablo_new ve _tablo_old gibi artık tablolarla tetikleyiciler geride kalabilir; çalıştırmadan önce bunları kontrol et:
SHOW TABLES LIKE '\_%\_new';
SELECT trigger_name, event_object_table FROM information_schema.triggers
WHERE trigger_schema = 'magaza';
Üçüncüsü, replika üzerinde bakım aracı çalıştırıp master'ı unutmaktır. pt-online-schema-change daima master üzerinde çalıştırılır; değişiklik replikasyon üzerinden replikalara akar. Doğrudan replikada çalıştırırsan replikasyonu bozarsın.
Dördüncüsü, yük koruma parametrelerini atlamaktır. Test ortamında sorunsuz çalışan bir pt-archiver komutu, üretimde --sleep ve --limit olmadan replikasyonu dakikalarca geride bırakabilir. Bu parametreleri "sonra eklerim" diye bırakma; ilk komutundan itibaren yaz. Bakım penceresi planlarken ayrıca fiziksel bir yedek almak istersen Percona XtraBackup ile sıcak yedekleme yazısındaki akış, toolkit ile birlikte çok iyi çalışır.
Sıkça Sorulan Sorular#
Percona Toolkit MariaDB ile çalışır mı#
Evet, araçların büyük çoğunluğu MariaDB ile sorunsuz çalışır çünkü aynı protokolü ve büyük ölçüde aynı sistem tablolarını kullanırlar. Yalnızca bazı sürüm kontrollerinde ve MariaDB'ye özgü özelliklerde uyarı alabilirsin; örneğin GTID uygulamaları iki üründe farklıdır. Kritik bir işlem öncesinde --dry-run ile prova yapmak, sürüm uyumsuzluğunu erkenden yakalamanın en pratik yoludur.
pt-online-schema-change ne kadar sürer#
Süre tamamen tablonun satır sayısına, disk hızına ve seçtiğin --chunk-size değerine bağlıdır. Birkaç milyon satırlık bir tablo genellikle dakikalar içinde biterken, yüz milyonluk bir tablo saatler sürebilir. Uygulama bu süre boyunca yazmaya devam edebildiği için toplam süre kesinti anlamına gelmez; asıl dikkat edilecek nokta işlem sırasında diskte tablonun iki kopyasının birden duracağıdır.
pt-table-checksum tutarsızlık bulursa ne yapmalıyım#
Önce paniğe kapılıp senkronizasyon başlatma; farkın kaynağını anlamaya çalış. Replikada elle yapılmış bir yazma, atlanan bir replikasyon hatası ya da bir tetikleyici farkı en yaygın sebeplerdir. Kaynağı bulduktan sonra pt-table-sync aracını önce --print ile çalıştırıp üreteceği SQL ifadelerini incele, doğru olduğuna ikna olduğunda --execute ile uygula ve mutlaka --sync-to-master kullan.
Percona Toolkit ücretsiz mi#
Percona Toolkit tamamen açık kaynaktır ve GPL lisansıyla ücretsiz dağıtılır; üretimde kullanmak için lisans satın alman gerekmez. Tüm araçlar ve seçenekleri ücretsiz sürümde mevcuttur. Percona firması yalnızca destek ve danışmanlık hizmetleri için ücret alır, yazılımın kendisi için değil.
pt-archiver yerine DELETE kullanamaz mıyım#
Küçük tablolarda kullanabilirsin ama büyük tablolarda tek bir DELETE ifadesi ciddi sorunlara yol açar. Milyonlarca satırı tek işlemde silmek devasa bir geri alma alanı üretir, tabloyu uzun süre meşgul eder, replikaları geride bırakır ve işlem yarıda kesilirse geri alma süreci silme işleminden bile uzun sürebilir. pt-archiver aynı işi küçük partiler hâlinde ve aralarda bekleyerek yaptığı için üretim ortamında çok daha güvenlidir.
Araçları veritabanı sunucusunda mı çalıştırmalıyım#
Zorunlu değil. Percona Toolkit araçları MySQL'e ağ üzerinden bağlanan istemcilerdir, bu yüzden ayrı bir yönetim makinesinden de çalıştırılabilirler. Yalnızca pt-summary gibi işletim sistemi bilgisi toplayan araçlar ve yavaş sorgu günlüğünü okuyan pt-query-digest, dosyalara erişmek için ilgili sunucuda çalışmak ister. Ayrı makineden çalıştırmak, ağır bir analizin veritabanı sunucusunun kaynaklarını tüketmesini de önler.
Kapanış#
Percona Toolkit, MySQL yönetimini "umarım sorun çıkmaz" seviyesinden ölçülebilir bir mühendislik pratiğine taşır. Aklında tutman gereken alışkanlıklar şunlar: veri değiştiren her araçta önce --dry-run veya --print çalıştır, üretimde --max-load, --max-lag ve --sleep gibi koruma parametrelerini asla atlama, şema değişikliklerini daima master üzerinde uygula ve replika tutarlılığını düzenli aralıklarla pt-table-checksum ile doğrula. Bir de büyük tabloları tek seferde silme alışkanlığını pt-archiver ile değiştir; bu tek değişiklik bile pek çok gece yarısı olayını önler.
Bu araçları rahatça çalıştırabileceğin, root erişimli bir ortama ihtiyacın olacak; VDS ve bulut sunucu paketlerimiz Percona depolarını kurup toolkit'i çalıştırmak için yeterli özgürlüğü sağlar. Bakım pencerelerini, şema değişikliklerini ve tutarlılık kontrollerini kendin üstlenmek istemiyorsan sunucu yönetimi hizmetimiz bu rutini devralır; işlemler öncesi kopyaları dış ortamda tutmak için yedekleme çözümlerimize bakabilirsin.