Geçen ay bir arkadaşım aradı, sesi titriyordu. “Veritabanı gitti” dedi. Hani o klişe film sahnelerindeki gibi — ama gerçek hayatta yaşanınca, inan bana, hiç komik değil. Bir UPDATE sorgusunda WHERE koşulunu unutmuş. Tüm müşteri tablosu tek bir değerle dolmuş, her satır aynı. Yedek? Yok. Geri dönüş? İmkânsız.
O günden sonra dedim ki bu konuyu düzgün bir yazıya dökmem şart. Çünkü veritabanı yedekleme, herkesin “evet evet yapıyorum” deyip aslında çoğu zaman es geçtiği bir şey. Ta ki başına bir şey gelene kadar.
Neden Yedek Almalısın? Cidden Neden?
“Yedek almak önemlidir” cümlesini herkes bilir (buna dikkat edin). Ama mesele şu: insanlar bunu genellikle afet olduktan sonra öğreniyor. Ben 2019’da küçük bir e-ticaret projesinde çalışırken, sunucu sağlayıcının disk arızası yüzünden 3 günlük veriyi kaybetmiştik. Yedek alıyorduk evet — ama haftalık. Aradaki 3 gün? Buhar oldu, gitti. Şimdi düşünüyorum da, o 3 günlük verinin içinde onlarca sipariş vardı muhtemelen (en azından benim deneyimim böyle)
Yedekleme sadece “sunucu çökerse” diye değil. Düşün bir:
- Bir geliştirici yanlış migration çalıştırabilir (bizzat yaşadım, 2021, İstanbul ofisi) (bence en önemlisi)
- Ransomware saldırısı veritabanını şifreleyebilir
- Test ortamına güncel veri lazım olabilir — bunu es geçmeyin
- Müşteri “3 ay önceki halini görebilir miyiz?” diyebilir
- Staging ve production arasında veri taşıman gerekebilir
Kısacası yedek almak, yangın söndürücü gibi bir şey. Kullanmak istemezsin ama olmadığında felaket yaşarsın. İşte, basit.
mysqldump Nedir, Ne Yapar?
MySQL’in kendi bünyesinde gelen, terminalde çalışan bir yedekleme aracı bu (ciddiyim). Veritabanını .sql uzantılı bir dosyaya döküyor — — en azından ben öyle düşünüyorum — içinde CREATE TABLE, INSERT INTO ve benzeri SQL ifadeleri oluyor — dürüst olayım, biraz hayal kırıklığı —. İlginç, değil mi? Yani aslında veritabanının tamamını bir metin dosyası olarak dışarı çekiyorsun, düz yazı olarak.
Bakın, burayı atlarsanız yazının kalanı anlamsız kalır.
Tuhaf ama, Basit mi? Evet. Kullanışlı mı? Bayağı. Ama her araçta olduğu gibi, ince ayarları bilmezsen eninde sonunda bir yerde takılırsın.
mysqldump küçük ve orta ölçekli veritabanları için harika çalışıyor. Ama 50 GB üzeri veritabanlarında farklı stratejiler düşünmen lazım — bu yazıda ona da değineceğim.
Ha bu arada, eğer SQL’in temellerine hakim değilsen veya DDL/DML kavramlarını tazelemek istersen, SQL’de DDL ve DML: Tablo Kurup Veri Oynamanın İncelikleri yazımız tam sana göre.
Temel Yedekleme Komutları
Tek bir veritabanını yedeklemek
Bence, En sık karşılaşılan senaryo bu. Diyelim ki magaza_db adında bir veritabanın var:
mysqldump -u root -p --databases magaza_db > magaza_yedek.sql
Bu komut sana eksiksiz bir SQL dosyası verecek. İçine baktığında CREATE DATABASE, CREATE TABLE ve INSERT satırlarını görürsün. Güzel, temiz. Ama dur bir saniye — bu kadar değil, devam edelim.
Tüm veritabanlarını tek seferde yedeklemek
Sunucuda birden fazla proje mi var? Hepsini tek hamlede al:
mysqldump -u root -p --all-databases > tum_yedek.sql
Bunu genellikle sunucu taşırken kullanıyorum. Geçen yıl bir müşterinin sitesini Hetzner’den DigitalOcean’a taşırken tam olarak bu komutu çalıştırdım — 12 veritabanı, tek dosya, 15 dakika. İşini gördü, lafı gevelemeye gerek yok.
Birden fazla ama hepsini değil
Seçici olmak istiyorsan:
mysqldump -u root -p --databases proje_a proje_b test_db > secili_yedek.sql
Hepsi bu kadar mı? Hayır, asıl incelik şimdi başlıyor.
Trigger, Procedure ve Function: Unutulan Detaylar
Bir keresinde — 2022’nin sonlarıydı sanırım — bir müşterinin yedeklerini geri yükledim. Her şey tamam gibi görünüyordu: tablolar geldi, veriler geldi. E sonra? Sipariş sistemi çalışmıyordu. Neden? Çünkü stored procedure’ler yedekte yoktu! mysqldump varsayılan olarak trigger’ları alıyor ama routine’leri, yani procedure ve function’ları, almıyor. Kim bilir kaç kişi bu tuzağa düştü.
Bu yüzden şu parametreleri aklına kazı:
# Trigger'larla birlikte (aslında varsayılan ama belirtmekte fayda var)
mysqldump -u root -p --triggers --all-databases > yedek_triggerli.sql
# Stored procedure ve function'larla birlikte
mysqldump -u root -p --routines --all-databases > yedek_routineli.sql
# Hepsini bir arada — benim favori kombinasyonum
mysqldump -u root -p --triggers --routines --events --all-databases > tam_yedek.sql
--events parametresi MySQL Event Scheduler’daki zamanlanmış görevleri de yedekler. Eğer cron benzeri işler veritabanı içinde tanımlıysa, bunu da eklemeyi unutma.Sıkıştırma: Disk Alanını Boşa Harcama
SQL dosyaları metin bazlı olduğu için çok iyi sıkışıyor. Ciddi ciddi çok iyi. Ben kendi projelerimde 900 MB’lık bir dump dosyasını gzip ile 280 MB’a, bzip2 ile 190 MB’a düşürdüğümü gördüm — rakamlar projeye göre değişir elbette. Oran genelde bu civarda kalıyor, büyük metin bloklarında sıkıştırma oranı daha da artabiliyor.
gzip ile sıkıştırma
mysqldump -u root -p --all-databases | gzip > yedek.sql.gz
Hızlı. Pratik. Günlük yedekler için genelde bunu tercih ediyorum.
bzip2 ile sıkıştırma
mysqldump -u root -p --all-databases | bzip2 > yedek.sql.bz2
Daha yavaş ama daha küçük dosya çıkıyor (buna dikkat edin). Arşivleme amaçlı — mesela aylık yedekler için — bzip2 daha mantıklı bir tercih.
| Yöntem | Örnek Boyut | Hız | Kullanım Senaryosu |
|---|---|---|---|
| Sıkıştırmasız | ~947 KB | En hızlı | Hızlı test, geçici yedek |
| gzip | ~297 KB | Hızlı | Günlük otomatik yedek |
| bzip2 | ~205 KB | Yavaş | Arşivleme, uzun süreli saklama |
Gördüğün gibi gzip bile boyutu üçte birine çekiyor (inanın bana). Bzip2’nin avantajı büyük dosyalarda daha belirgin oluyor — 10 GB üzeri dump’larda fark gerçekten hissedilir, saatlerce süren aktarımlarda bu küçük fark önem kazanıyor. Daha fazla bilgi için Doki Doki Play Store’dan Neden Uçtu? Sansürün İnce Çizgisi yazımıza bakabilirsiniz.
Geri Yükleme: Asıl Kritik Olan Kısım
Açık konuşayım. Yedek almak işin kolay tarafı. Asıl mesele o yedeği sorunsuz geri yükleyebilmek — hiç test etmediğin bir yedek, yedek sayılmaz. Nokta. Bu konuyla ilgili Yapay Zekâ Artık Her Şeyi Dokunuyor: Sağlık, Kod, Lisans yazımıza da göz atmanızı tavsiye ederim.
Normal SQL dosyasını geri yüklemek
mysql -u root -p < yedek.sql
Basit. Ama dikkat — eğer aynı isimde veritabanı varsa, DROP DATABASE komutu çalışacak ve mevcut veriyi silecek. Yani geri yükleme yapmadan önce nereye yüklediğini kesinlikle bil.
gzip’li yedeği geri yüklemek
gunzip < yedek.sql.gz | mysql -u root -p
bzip2’li yedeği geri yüklemek
bunzip2 < yedek.sql.bz2 | mysql -u root -p
gunzip < yedek.sql.gz | mysql -u root -pbunzip2 < yedek.sql.bz2 | mysql -u root -pBir de şunu söyleyeyim — büyük dosyalarda geri yükleme ciddi uzun sürebilir (ki bu çoğu kişinin gözünden kaçıyor). 5-6 GB’lık bir dump’ı geri yüklerken 2 saat beklediğim oldu, sabırsızlanıp terminal penceresini kapatan olursa işlem durur. screen veya tmux kullan ki SSH bağlantısı koparsa işlem arka planda devam etsin. Siz hiç denediniz mi? Bu detayı kimse anlatmıyor ama hayat kurtarıyor, söz.
Otomasyon: Cron ile Yedeklemeyi Unutma
İnanın, Elle yedek almak? İlk hafta yaparsın, ikinci hafta hatırlarsın, üçüncü hafta unutursun. Dördüncü hafta felaket olur. Bu yüzden cron job kur ve kafandan at (yanlış duymadınız)
# Her gece saat 03:00'te yedek al
0 3 * * * mysqldump -u root -pSENINSIFREN --triggers --routines --all-databases | gzip > /home/yedekler/db_$(date +\%Y\%m\%d).sql.gz
Hmm, bir saniye — burada şifreyi düz metin olarak yazdık, değil mi? Bu güvenlik açısından kötü, gerçekten kötü. Daha sağlıklı yöntem ~/.my.cnf dosyası kullanmak:
# ~/.my.cnf dosyası
[mysqldump]
user=root
password=SENINSIFREN
Sonra chmod 600 ~/.my.cnf ile sadece senin okuyabilmeni sağla (kendi tecrübem). Artık komutta -u ve -p yazman gerekmez, sistem otomatik alır.
Bir de eski yedekleri temizlemeyi unutma. 30 günden eski dosyaları silen bir satır ekle: Daha fazla bilgi için Benjamin Franklin’in Evinin Altındaki Karanlık Sır yazımıza bakabilirsiniz.
find /home/yedekler/ -name "*.sql.gz" -mtime +30 -delete
Büyük Veritabanları İçin Ne Yapmalı?
Bir şey dikkatimi çekti: mysqldump küçük ve orta boy projeler için — tamam, “mükemmel” demeyeyim ama — bayağı iyi iş çıkarıyor. Ama 50 GB üzeri veritabanlarında sıkıntı çıkmaya başlıyor: yedek alma saatler sürebilir, geri yükleme daha da uzun. Maalesef.
Bu durumda alternatiflere bakmak lazım:
- Percona XtraBackup: Hot backup yapabiliyor — yani veritabanı çalışırken, kilitlemeden yedek alıyor. Enterprise projeler için olmazsa olmaz.
- MySQL Enterprise Backup: Oracle’ın resmi çözümü. Paralı ama kurumsal destek var.
- mydumper/myloader: mysqldump’ın çok thread’li alternatifi. Paralel çalıştığı için büyük veritabanlarında ciddi hız farkı yaratıyor.
Küçük bir startup için mysqldump fazlasıyla yeterli, bunu net söyleyebilirim. Ama enterprise seviyede — diyelim ki günde milyonlarca satır eklenen bir log tablosu var — o zaman XtraBackup veya mydumper’a geçmek şart. Ben geçen yıl bir fintech projesinde mydumper’a geçtik, yedek süresi 4 saatten 45 dakikaya düştü. Ciddi fark var.
Şahsen, AWS üzerinde çalışıyorsan, S3’ü Disk Gibi Bağlamak: AWS’nin Yeni Hamlesi yazımıza da göz atabilirsin — yedekleri S3’e aktarmak çok yaygın bir pratik.
İyi Pratikler: Yedekleme Stratejin Nasıl Olmalı?
Lafı gevelemeden söyleyeyim: yedek almak tek başına yetmiyor. Bir stratejin olmalı, kafanda netleşmiş bir plan.
- 3-2-1 kuralı: 3 kopya, 2 farklı ortam, 1 tanesi off-site (bulut veya farklı lokasyon)
- Yedekleri TEST ET: Ayda en az bir kere geri yükleme testi yap. Test etmediğin yedek, yedek değildir.
- Retention policy belirle: Günlük yedekleri 7 gün, haftalık yedekleri 1 ay, aylık yedekleri 1 yıl sakla.
- Yedek boyutlarını izle: Yedek boyutu aniden küçüldüyse — dur bir dakika! Belki tablolar boşalmıştır veya başka bir sorun vardır.
- Şifreleme: Yedek dosyalarını
opensslveyagpgile şifrele. Bilhassa buluta yüklüyorsan bu adımı atlama. (bu kritik)
Kısacası, bir de şunu ekleyeyim: yedek aldığın sırada veritabanında yazma işlemi oluyorsa tutarsız veri alabilirsin — bu gerçekten can sıkıcı bir durum. --single-transaction parametresi InnoDB tabloları için bu sorunu çözüyor:
mysqldump -u root -p --single-transaction --triggers --routines --all-databases | gzip > yedek.sql.gz
Aslında, MyISAM kullanıyorsan bu parametre işe yaramaz — o zaman --lock-all-tables kullanman gerekir ki bu da yedek süresince büyük çoğunluk tabloları kilitler. Yani… InnoDB kullanın arkadaşlar. 2025’teyiz.
Sıkça Sorulan Sorular
mysqldump ile alınan yedek ne kadar sürede geri yüklenir?
Bu neredeyse tamamen veritabanı boyutuna ve sunucu performansına bağlı. 1 GB’lık bir dump genelde 5-15 dakika sürer. 10 GB üzerinde saatleri bulabilir. SSD kullanan bir sunucuda çok daha hızlı oluyor (inanın bana). Büyük veritabanlarında --disable-keys ve --extended-insert parametreleri geri yükleme hızını artırabilir.
mysqldump çalışırken veritabanı kilitlenir mi?
InnoDB tabloları için --single-transaction parametresini kullanırsan kilitlenme olmaz. MyISAM tablolarında ise varsayılan olarak tablolar kilitlenir. Canlı bir üretim sunucusunda yedek alıyorsan, kesinlikle --single-transaction kullan.
Yedek dosyasını farklı bir MySQL sürümüne geri yükleyebilir miyim?
Yani, Genelde evet, ama dikkatli ol. Eski sürümden yeniye geçiş genellikle sorunsuz. Yeniden eskiye geçişte ise uyumluluk sorunları çıkabilir — özellikle yeni sürüme özgü SQL sözdizimi varsa. Her zaman önce test ortamında dene.
mysqldump yerine ne kullanabilirim?
Büyük veritabanları için Percona XtraBackup (fiziksel yedek, çok daha hızlı), mydumper (çok thread’li mantıksal yedek) veya MySQL Enterprise Backup alternatifleri var. Bulut kullanıyorsan RDS snapshot gibi platform seviyesi yedekleme seçenekleri de mevcut (yanlış duymadınız)
Sadece tek bir tabloyu yedekleyebilir miyim?
Evet! mysqldump -u root -p veritabani_adı tablo_adı > tablo_yedek.sql komutuyla tek bir tabloyu yedekleyebilirsin. Hatta birden fazla tablo adı da yazabilirsin, boşlukla ayırarak.
Kaynaklar ve İleri Okuma
Burada, bir şey dikkatimi çekti: MySQL Resmi Dokümantasyonu — mysqldump
Tuhaf ama, Percona XtraBackup — Açık Kaynak Hot Backup Aracı
Küçük bir detay: mydumper GitHub Sayfası — Çok Thread’li MySQL Yedekleme
Bu içerik işinize yaradı mı?
Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.



