Otomatik Yedekleme İncelemesi: Sessizce Başarısız Olduğunda

Aylardır hatasız çalışan ama dosyası boş olan otomatik yedekleme, mümkün olan en kötü senaryodur. Burada sessiz başarısızlığı felaketten önce nasıl yakalayacağınızı öğreneceksiniz.

6 dk Güncellendi 26 Oct 2026

Cron job'ı açıyorsunuz, yedekleme satırı yerinde, log da başarılı satırlarla dolu. Ama sunucuyu kaybettiğinizde ve yedek dosyasına baktığınızda, boyutu 20 kilobayt. Birkaç yorum satırı içeren boş bir SQL dosyası. İşte tam da bu durum, "otomatik yedekleme incelemesini" törensel bir işten bir zorunluluğa dönüştürüyor. Sessizce başarısız olan bir yedek, hiç yedek olmamasından daha tehlikelidir, çünkü içiniz rahattır ve sorunu aramazsınız.

Otomatik yedekleme neden hatasız görünürken başarısız olur

Pratikte üç senaryoyu çok gördüm ve üçünün de ortak bir kalıbı var: betik sıfır çıkış koduyla bitiyor ama beklediğiniz iş yapılmamış.

  • Şifre değişmiş. Biri MySQL kullanıcısının şifresini panelden değiştirmiş, ama ~/.my.cnf hâlâ eski şifreyi tutuyor. mysqldump Access denied for user hatasıyla çıkıyor, ama çıktı dosyaya yönlendirildiği için dosya oluşturuluyor ve boş kalıyor.
  • Disk dolmuş. Dünkü yedek yarım yazılmış ve bugün hiç yer kalmamış. Eğer rotasyon (döndürme) doğru ayarlanmamışsa, eski sürümler silinmiyor ve disk sessizce doluyor.
  • Yol değişmiş. Yeni bir veritabanı eklenmiş veya /var/www yolu /srv/app konumuna taşınmış ve betik hâlâ eski yolu arıyor. rsync var olmayan yolda hata veriyor ama komutun sonunda || true varsa, hata yutuluyor.

Ortak nokta şu: bunların hiçbiri crontab'da görünmüyor. Cron sadece komutun çalıştırıldığını biliyor. Sonucun ne olduğunu bilmiyor.

Sessiz başarısızlığı gerçekten yakalayan üç kontrol

Dosyanın varlığını değil, boyutunu kontrol edin

Yedek dosyasının varlığı hiçbir şeyi kanıtlamaz. Boyutu çok şey kanıtlar. Son yedeğin boyutunu dünkü boyutla karşılaştıran basit bir betik, çoğu hatayı yakalar:

#!/bin/bash
LAST=$(stat -c%s /backup/db-$(date -d yesterday +%F).sql.gz)
TODAY=$(stat -c%s /backup/db-$(date +%F).sql.gz)
if [ "$TODAY" -lt $((LAST / 2)) ]; then
  echo "backup shrank: $LAST -> $TODAY" | mail -s "BACKUP ALERT" ops@example.com
fi

Eğer bugün yedeğin boyutu dünkünün yarısından azsa, bir şeylerin ters gittiği anlamına gelir. Bu basit eşik, pratikte herhangi bir karmaşık izleme sisteminden daha iyi çalışır. Sayıyı verinizin gerçek büyümesine göre ayarlayın; günlük %5 büyümeniz varsa, %50 düşüş kesinlikle hata demektir.

Çıkış kodunu ciddiye alın

crontab'da komut hatayla biterse, cron bir e-posta gönderir. Ama sadece MAILTO ayarlanmışsa ve sunucuda MTA varsa. Günümüz sunucularının çoğunda hiçbiri yok. Daha güvenilir yol, çıkış kodunu betiğin kendisinde yakalamaktır:

mysqldump --single-transaction --routines --triggers \
  --databases app_db | gzip > /backup/db-$(date +%F).sql.gz
if [ ${PIPESTATUS[0]} -ne 0 ]; then
  curl -s -X POST https://hooks.example.com/alert -d "dump failed"
fi

Dikkat edin, $? değil ${PIPESTATUS[0]} kontrol ediyoruz. Çünkü $? gzip'in çıkış kodunu döndürür ve gzip boş girdide bile başarılı olur. İşte burada hata yapılıyor: birçok kişi $? koyuyor ve aylarca yedeğin sağlam olduğunu sanıyor, oysa her gece hiçlikten gzip'lenmiş bir dosya oluşturuyorlar.

Yedekleme testi değil, geri yükleme testi

Bir kez bile geri yüklenmemiş yedek, yedek değildir; bir dosyadır. Ayda bir kez ayrı bir sunucuda bunu çalıştırın:

gunzip -c /backup/db-2025-01-15.sql.gz | mysql -u root -p restore_test
mysql -u root -p -e "SELECT COUNT(*) FROM restore_test.orders;"

Eğer kayıt sayısı ana sunucuyla uyuşuyorsa, yedek sağlamdır. Eğer ERROR 1064 veya Table doesn't exist hatası aldıysanız, dosya eksiktir. Bu testi ana sunucuda çalıştırmayın; canlı veritabanına zarar verebilirsiniz. Ayrı bir sunucunuz yoksa, bunun için geçici bir bulut sunucusu yeterlidir.

Yedekleme yöntemlerinin karşılaştırması ve gerçek maliyetleri

YöntemAvantajGizli maliyet
Günlük mysqldumpBasit, okunabilir, düzenlenebilirBüyük veritabanlarında kilit ve yavaşlama yaratır
rsync dosyalarSadece değişiklikleri aktarır--delete vermezseniz silinen dosyalar hedefte kalır
LVM snapshotHızlı, hizmet kesintisi olmadanAynı diskte; disk arızasıyla birlikte kaybolur
xtrabackup ile sıcak yedekTablo kilidi olmadanİki kat disk alanı ve hassas yapılandırma gerektirir

Çoğu proje için tercihim: 50 gigabayt altındaki veritabanları için --single-transaction ile mysqldump, üstündekiler için xtrabackup. Veritabanınız 50 gig altındaysa ve xtrabackup'a yöneliyorsanız, gereksiz karmaşıklık satın alıyorsunuz. Tersi de doğru: 200 gig'lık bir veritabanında mysqldump her gece birkaç saat kilit koyar ve kullanıcılarınız kesinti hisseder.

Yedeği nerede tuttuğunuz, yedeğin kendisinden daha önemlidir

Aynı sunucudaki yedek, yedek değildir. Sunucu kaybolursa, ikisi birlikte gider. En az bir kopya başka bir yerde olmalı. SSH üzerinden rsync en basit yoldur:

rsync -avz --delete -e "ssh -p 2222" /backup/ backup@remote:/mnt/backups/$(hostname)/

Dikkat edin, SSH portunu açıkça belirttim. Varsayılan portu değiştirdiyseniz ve bunu yazmazsanız, rsync Connection refused ile reddedilir ve cron'daysa sadece sonuçsuz bir e-posta gönderir. Hangi portların açık olması gerektiğini ve hangilerinin gerekmediğini bilmek için yaygın servis portları referansına bakın.

Şifreleme hakkında bir not: yedeği üçüncü taraf bir sunucuya koyuyorsanız, aktarım öncesi şifreleyin. gpg --encrypt veya openssl enc -aes-256-cbc ikisi de işe yarar. Anahtarı yedeği alan sunucuda tutmayın; sunucu kaybolursa anahtar da gider ve yedek kurtarılamaz hale gelir.

İzleme: dün gece yedeklemenin çalıştığını nasıl anlarsınız

En basit yol, bir işaret dosyasıdır (heartbeat). Yedekleme betiği başarıyla tamamlandığında bugünün tarihiyle bir dosya oluşturur. Ayrı bir betik her sabah bu dosyanın bugüne ait olup olmadığını kontrol eder:

find /backup/.heartbeat -mtime +1 -type f | grep -q . && \
  echo "backup stale" | mail -s "ALERT" ops@example.com

Bu yöntem log tabanlı izlemeden daha güvenilirdir, çünkü log dolabilir ve dönebilir, ama işaret dosyası sadece yedekleme gerçekten bittiğinde oluşturulur. Daha derine inmek ve sunucunun neden yavaşladığını veya yedeklemenin neden uzun sürdüğünü anlamak istiyorsanız, yüksek sunucu yükünü teşhis rehberi iyi bir başlangıç noktasıdır.

Sunucuyu yeni kurduysanız ve henüz yedekleme yapısını oluşturmadıysanız, her şeyden önce Linux dağıtımı seçimini ciddiye alın, çünkü yedekleme araçları farklı dağıtımlarda pratik farklılıklar gösterir. Ve eğer bir özel sunucuda çalışıyorsanız, disk alanını baştan yedekleme için ayırın, kök bölümüne değil.

Sık sorulan sorular

Otomatik yedeklemenin gerçekten çalıştığını nasıl anlarım?

Dosyanın varlığına değil, değişiklik zamanına bakın. stat /backup/db-$(date +%F).sql.gz komutu bugünün tarihini göstermelidir. Dosya varsa ama tarih dün veya daha eskiyse, yedekleme çalışmamış veya yarım kalmıştır.

Daha güvenilir yol, işaret dosyasıdır: yedekleme betiği başarıyla tamamlandığında bugünün tarihiyle boş bir dosya oluştursun ve ayrı bir betik her sabah varlığını kontrol etsin.

MySQL yedek dosyam neden boş?

Neredeyse her zaman kimlik doğrulama hatası veya erişim eksikliğinden kaynaklanır. Eğer mysqldump veritabanına bağlanamazsa, hatayı stderr'e yazar ama çıktı dosyaya yönlendirildiği için boş bir dosya oluşturulur ve çıkış kodu da sıfır olabilir.

Çözüm: ${PIPESTATUS[0]} çıkış kodunu kontrol edin ve ~/.my.cnf'nin güncel şifreyi tuttuğundan emin olun. Aynı komutu bir kez elle çalıştırın ve çıktıyı görün.

Yedek geri yüklemeyi ne sıklıkla test etmeliyim?

Ayda en az bir kez. Veriniz kritikse, iki haftada bir. Geri yükleme testini ana sunucuda yapmayın; ayrı bir ortam oluşturun ve dosyayı orada açın.

Başarı ölçütü, ana tablonun kayıt sayısının geri yüklenen sürümle uyuşmasıdır. Sadece dosyayı açıp hata almadıysanız, test etmemişsinizdir.

Aynı sunucudaki yedek yeterli değil mi?

Hayır. Disk veya sunucu kaybolursa, yedek de onunla gider. En az bir kopya ayrı bir hedefte olmalı, tercihen başka bir veri merkezinde.

Yedeği şifreliyorsanız, anahtarı başka bir yerde tutun. Anahtarın aynı sunucuda olması, asla açamayacağınız şifrelenmiş bir yedek anlamına gelir.

Bugün bir kez elle yedekleme betiğini çalıştırın ve çıktı dosyasının boyutuna bakın. Beklediğinizden küçükse, yarına kadar beklemeyin.

Bu sayfa yardımcı oldu mu?