Veritabanı Yedeği için mysqldump Sorgu Örnekleri
Veritabanı yönetiminde en kritik konulardan biri düzenli ve güvenilir yedekleme yapmaktır. Production ortamında bir şeyler ters gittiğinde, elinizdeki tek can simidi o yedek dosyasıdır. MySQL ve MariaDB dünyasında mysqldump aracı, yıllardır sysadmin’lerin vazgeçilmezi olmaya devam ediyor. Basit görünse de, parametrelerini ve kullanım senaryolarını iyi bilmeden yapılan yedekler sizi zor anında hayal kırıklığına uğratabilir. Bu yazıda gerçek dünya senaryolarıyla mysqldump kullanımını tüm detaylarıyla ele alacağız.
mysqldump Nedir ve Nasıl Çalışır?
mysqldump MySQL ve MariaDB ile birlikte gelen bir komut satırı yardımcı programıdır. Veritabanı yapısını ve verilerini SQL formatında dışa aktarır. Oluşturduğu dosya, içinde CREATE TABLE, INSERT INTO gibi SQL ifadelerini barındıran düz metin bir dosyadır. Bu dosyayı herhangi bir MySQL/MariaDB sunucusuna geri yükleyebilirsiniz.
Çalışma prensibi şudur: mysqldump veritabanına bağlanır, tablo yapılarını ve verileri okur, bunları SQL komutlarına çevirir ve belirttiğiniz dosyaya yazar. Bu süreçte tablolar geçici olarak kilitlenebilir, bu yüzden büyük production veritabanlarında dikkatli olmak gerekir.
Temel Kullanım ve Bağlantı Parametreleri
En basit haliyle bir veritabanını yedeklemek için:
mysqldump -u kullanici_adi -p veritabani_adi > yedek.sql
Bu komutu çalıştırdığınızda sistem sizden şifre isteyecektir. Production ortamında otomatik yedekleme scriptleri için şifreyi interaktif girmek pratik değildir. Bu durumda birkaç seçeneğiniz var.
Seçenek 1: Şifreyi komut satırına yazmak (güvensiz)
mysqldump -u root -pSifreniz veritabani_adi > yedek.sql
Bu yöntemi kesinlikle tavsiye etmiyorum çünkü şifre ps aux çıktısında görünür.
Seçenek 2: .my.cnf dosyası kullanmak (önerilen)
# /root/.my.cnf dosyası oluşturun
cat > /root/.my.cnf << EOF
[mysqldump]
user=root
password=GucluSifreniz
[mysql]
user=root
password=GucluSifreniz
EOF
# Dosya izinlerini düzeltin
chmod 600 /root/.my.cnf
Bu ayarı yaptıktan sonra şifre parametresi olmadan çalıştırabilirsiniz:
mysqldump veritabani_adi > yedek.sql
Sık Kullanılan Parametreler
mysqldump onlarca parametre sunar. Günlük işlerde en çok işinize yarayacakları şöyle sıralayabilirim:
- -u: Kullanıcı adını belirtir
- -p: Şifre istemek için kullanılır
- -h: Host adresini belirtir, varsayılan localhost’tur
- -P: Port numarasını belirtir, varsayılan 3306’dır
- –all-databases: Tüm veritabanlarını yedekler
- –databases: Birden fazla veritabanı belirtmek için kullanılır
- –single-transaction: InnoDB tablolar için kilitlemesiz yedek alır
- –lock-tables: MyISAM tablolar için tablo kilitleme yapar
- –no-data: Sadece tablo yapısını alır, veri almaz
- –no-create-info: Sadece veriyi alır, tablo yapısını almaz
- –where: Belirli koşulla filtrelenmiş veri alır
- –compress: Sunucu ile istemci arasındaki veriyi sıkıştırır
- –routines: Stored procedure ve function’ları dahil eder
- –triggers: Trigger’ları dahil eder, varsayılan olarak aktiftir
- –events: Event scheduler’daki event’leri dahil eder
- –hex-blob: BLOB alanlarını hexadecimal formatında yazar
- –add-drop-table: Her CREATE TABLE’dan önce DROP TABLE ekler
- –skip-add-drop-table: DROP TABLE ifadelerini eklemez
- –extended-insert: Daha hızlı ve kompakt INSERT ifadeleri kullanır
- –quick: Büyük tablolar için satır satır okuma yapar, bellek tasarrufu sağlar
Senaryo 1: Tek Veritabanı Yedeği
En yaygın kullanım senaryosu tek bir veritabanını yedeklemektir. Bir e-ticaret sitesinin veritabanını yedeklediğimizi düşünelim:
mysqldump
-u backup_user
-p
--single-transaction
--routines
--triggers
--events
--hex-blob
--quick
eticaret_db > /backup/eticaret_db_$(date +%Y%m%d_%H%M%S).sql
Burada --single-transaction parametresine dikkat edin. Bu parametre InnoDB motorunu kullanan tablolarda yedeği bir transaction içinde alır ve tabloları kilitlemez. Production ortamında kullanıcılar veritabanına yazmaya devam ederken yedek alabilirsiniz. Ancak bu sadece InnoDB için geçerlidir, MyISAM tablolarınız varsa --lock-tables kullanmanız gerekir.
Senaryo 2: Tüm Veritabanlarını Yedeklemek
Sunucuda birden fazla veritabanı varsa hepsini tek seferde yedeklemek için:
mysqldump
-u root
--all-databases
--single-transaction
--routines
--triggers
--events
--master-data=2
--flush-logs
> /backup/full_backup_$(date +%Y%m%d_%H%M%S).sql
--master-data=2 parametresi yorum satırı olarak binary log pozisyonunu dosyaya yazar. Bu, replikasyon kurulumlarında veya point-in-time recovery için çok işinize yarayacak bir bilgidir. --flush-logs ise yedek başlamadan önce binary logları döndürür.
Birden fazla ama belirli veritabanlarını yedeklemek için:
mysqldump
-u root
--databases musteri_db siparis_db urun_db
--single-transaction
> /backup/secili_veritabanlari_$(date +%Y%m%d).sql
Senaryo 3: Sadece Yapı veya Sadece Veri Almak
Bazen tablonun sadece yapısına ihtiyacınız olur, bazen de sadece veriye. Örneğin bir test ortamı kurarken production veritabanının yapısını kopyalamak isteyebilirsiniz:
# Sadece tablo yapısını al (veri olmadan)
mysqldump
-u root
--no-data
--routines
--triggers
production_db > /tmp/yapi_sadece.sql
# Test veritabanına uygula
mysql -u root test_db < /tmp/yapi_sadece.sql
Tersine, mevcut bir yapıya yeni veri yüklemek için:
# Sadece veriyi al
mysqldump
-u root
--no-create-info
--skip-add-drop-table
production_db > /tmp/veri_sadece.sql
Senaryo 4: Belirli Tabloları Yedeklemek
Bazen tüm veritabanını değil, sadece belirli tabloları yedeklemeniz gerekir. Log tablolarını veya büyük geçmiş tablolarını atlamak isteyebilirsiniz:
# Belirli tabloları yedekle
mysqldump
-u root
musteri_db
musteriler siparisler urunler
--single-transaction
> /backup/onemli_tablolar.sql
Büyük log tablolarını atlayarak yedek almak için --ignore-table kullanabilirsiniz:
mysqldump
-u root
--single-transaction
--ignore-table=musteri_db.islem_loglari
--ignore-table=musteri_db.hata_loglari
musteri_db > /backup/musteri_db_noslog.sql
Senaryo 5: Koşullu Veri Yedekleme
--where parametresi ile belirli koşulları sağlayan kayıtları yedekleyebilirsiniz. Bu özellikle büyük tablolarda belirli bir tarih aralığını veya belirli kayıtları almanız gerektiğinde çok işe yarar:
# Son 30 günün siparişlerini al
mysqldump
-u root
--single-transaction
--where="created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)"
eticaret_db siparisler
> /backup/son30gun_siparisler.sql
# Belirli bir müşterinin verilerini al
mysqldump
-u root
--where="musteri_id = 12345"
eticaret_db siparisler siparis_detaylari
> /tmp/musteri_12345_verileri.sql
Bu senaryoyu gerçek hayatta sıkça kullanıyorum. Örneğin bir müşteri “benim verilerimi sil” talep ettiğinde, silmeden önce o müşteriye ait tüm verileri arşivlemem gerekiyor. --where parametresi burada hayat kurtarıcı oluyor.
Sıkıştırılmış Yedek Almak
Büyük veritabanlarında yedek dosyaları çok yer kaplayabilir. Doğrudan sıkıştırarak yedek almak disk alanından önemli ölçüde tasarruf sağlar:
# gzip ile sıkıştır
mysqldump
-u root
--single-transaction
--quick
buyuk_veritabani | gzip -9 > /backup/buyuk_db_$(date +%Y%m%d).sql.gz
# bzip2 ile daha iyi sıkıştırma (daha yavaş)
mysqldump
-u root
--single-transaction
buyuk_veritabani | bzip2 > /backup/buyuk_db_$(date +%Y%m%d).sql.bz2
# xz ile en iyi sıkıştırma (en yavaş)
mysqldump
-u root
--single-transaction
buyuk_veritabani | xz > /backup/buyuk_db_$(date +%Y%m%d).sql.xz
Gzip genellikle en iyi denge noktasıdır. Ortalama bir veritabanı için %70-80 oranında sıkıştırma sağlayabilirsiniz.
Otomatik Yedekleme Script’i
İşte production ortamında kullandığım, biraz geliştirilmiş bir yedekleme scripti:
#!/bin/bash
# /usr/local/bin/db_backup.sh
# Konfigürasyon
BACKUP_DIR="/backup/mysql"
RETENTION_DAYS=7
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/mysql_backup.log"
MYSQL_USER="backup_user"
# Bildirim fonksiyonu
log_message() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# Backup dizinini oluştur
mkdir -p "$BACKUP_DIR"
log_message "Yedekleme basliyor..."
# Tüm veritabanlarını listele (system veritabanları hariç)
DATABASES=$(mysql -u "$MYSQL_USER" -e "SHOW DATABASES;" |
grep -Ev "^(Database|information_schema|performance_schema|sys|mysql)$")
# Her veritabanı için ayrı yedek al
for DB in $DATABASES; do
log_message "Yedekleniyor: $DB"
OUTPUT_FILE="$BACKUP_DIR/${DB}_${DATE}.sql.gz"
if mysqldump
-u "$MYSQL_USER"
--single-transaction
--routines
--triggers
--events
--hex-blob
--quick
"$DB" | gzip -6 > "$OUTPUT_FILE"; then
SIZE=$(du -sh "$OUTPUT_FILE" | cut -f1)
log_message "Basarili: $DB -> $OUTPUT_FILE ($SIZE)"
else
log_message "HATA: $DB yedeklenemedi!"
# Hata durumunda e-posta gönder
echo "HATA: $DB veritabani yedeklenemedi! Sunucu: $(hostname)" |
mail -s "MySQL Yedekleme Hatasi" [email protected]
fi
done
# Eski yedekleri temizle
log_message "Eski yedekler temizleniyor (${RETENTION_DAYS} gunden eski)..."
find "$BACKUP_DIR" -name "*.sql.gz" -mtime "+$RETENTION_DAYS" -delete
log_message "Yedekleme tamamlandi."
Bu scripti crontab’a eklemek için:
# Crontab'ı düzenle
crontab -e
# Her gece 02:00'de çalıştır
0 2 * * * /usr/local/bin/db_backup.sh
Yedeği Geri Yüklemek
Yedeği almak kadar önemli olan bir konu da yedeği düzgün geri yükleyebilmektir. Düzenli aralıklarla restore testleri yapmanızı kesinlikle tavsiye ederim.
# Düz SQL dosyasını geri yükle
mysql -u root -p veritabani_adi < yedek.sql
# Gzip'li yedeği doğrudan geri yükle
gunzip -c yedek.sql.gz | mysql -u root -p veritabani_adi
# Yeni bir veritabanı oluşturup geri yükle
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS yeni_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -u root -p yeni_db < yedek.sql
# --all-databases ile alınan yedeği geri yükle
mysql -u root -p < full_backup.sql
Uzak Sunucudan Yedek Almak
Bazen yerel sunucudan değil, uzaktaki bir veritabanı sunucusundan yedek almanız gerekebilir:
# Uzak sunucudan yedek al ve yerel diske kaydet
mysqldump
-h 192.168.1.100
-P 3306
-u backup_user
-p
--single-transaction
production_db | gzip > /local/backup/remote_backup_$(date +%Y%m%d).sql.gz
# SSH tüneli üzerinden güvenli bağlantı
ssh -L 3307:localhost:3306 user@uzak_sunucu -N &
mysqldump
-h 127.0.0.1
-P 3307
-u backup_user
-p
production_db > /backup/guvenli_yedek.sql
Yedekleme Kullanıcısı Oluşturmak
Root kullanıcısıyla yedekleme yapmak güvenlik açısından iyi bir pratik değildir. Sadece gerekli yetkilere sahip bir yedekleme kullanıcısı oluşturmalısınız:
# MySQL'e bağlan ve yedekleme kullanıcısı oluştur
mysql -u root -p << EOF
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'GucluBirSifre123!';
GRANT SELECT, SHOW VIEW, RELOAD, REPLICATION CLIENT, EVENT, TRIGGER ON *.* TO 'backup_user'@'localhost';
GRANT LOCK TABLES ON *.* TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;
EOF
Bu kullanıcı sadece okuma ve yedekleme işlemleri için gerekli yetkilere sahip olacak, verileri değiştiremeyecektir.
Yedek Dosyasını Doğrulamak
Aldığınız yedeğin sağlıklı olup olmadığını kontrol etmek için birkaç yöntem:
# Dosya boyutunu kontrol et (0 byte ise bir şeyler yanlış)
ls -lh /backup/yedek.sql.gz
# Gzip dosyasının bütünlüğünü kontrol et
gunzip -t /backup/yedek.sql.gz && echo "Dosya saglikli" || echo "HATA: Dosya bozuk"
# SQL dosyasının başına bak
gunzip -c /backup/yedek.sql.gz | head -50
# Satır sayısını kontrol et
gunzip -c /backup/yedek.sql.gz | wc -l
# mysqldump'ın sonuna eklediği tamamlanma yorumunu kontrol et
gunzip -c /backup/yedek.sql.gz | tail -5
Sağlıklı bir mysqldump çıktısının sonunda şuna benzer bir satır görmelisiniz:
-- Dump completed on 2024-01-15 02:05:33
Bu satırı göremiyorsanız yedek tamamlanmamış demektir.
Performans İpuçları
Büyük veritabanlarında yedekleme sürecini hızlandırmak ve sunucuyu daha az yormak için bazı öneriler:
--quickparametresini her zaman kullanın. Bu parametre büyük tablolarda veriyi tüm belleğe yüklemek yerine satır satır okur.--compressparametresi sunucu ile istemci arasındaki ağ trafiğini azaltır, uzak sunuculardan yedek alırken kullanışlıdır.- Yedekleme işlemlerini off-peak saatlere, yani trafiğin en az olduğu gece saatlerine planlayın.
- Çok büyük veritabanları için
mydumperaracını araştırabilirsiniz. Parallel dump özelliğiyle çok daha hızlı yedek alabilir. niceveionicekomutlarıyla yedekleme prosesinin önceliğini düşürerek sunucunun ana işlerine daha fazla kaynak ayırmasını sağlayabilirsiniz:
nice -n 19 ionice -c 3 mysqldump -u root --single-transaction buyuk_db | gzip > /backup/buyuk_db.sql.gz
Sonuç
mysqldump belki eski bir araç ama hala işlevselliğini koruyor ve küçük ile orta ölçekli veritabanları için yeterince güvenilir. Önemli olan doğru parametreleri kullanmak, düzenli test etmek ve yedekleme sürecini izlemek.
Burada özetlemek istediğim temel noktalara bakacak olursak: Production InnoDB veritabanlarında her zaman --single-transaction kullanın, root yerine kısıtlı yetkili bir yedekleme kullanıcısı oluşturun, --routines --triggers --events parametrelerini unutmayın, yedekleri sıkıştırın ve birden fazla konuma (farklı disk, uzak sunucu, bulut depolama) yedek alın.
En önemli kural ise şudur: Test etmediğiniz yedek, yedek değildir. Ayda en az bir kez yedeklerinizi test ortamında geri yükleyin ve çalıştığından emin olun. Gün gelir bir şeyler ters gider ve o anda elinizdeki yedeğin gerçekten işe yaradığını önceden bilmek, tüm stresi ortadan kaldırır.
