itsrda

MariaDB için Otomatik Yedekleme: mysqldump, Rotasyon ve Geri Yükleme Testi

Her gece çalışan, eski yedekleri temizleyen ve asıl önemlisi geri yüklenebildiği doğrulanan bir MariaDB yedekleme düzeni nasıl kurulur? Betik, systemd timer ve test yöntemi.

Yedekleme konusundaki en pahalı ders şudur: yedeği olan değil, geri yükleyebilen kişi güvendedir. Birçok kurulumda yedek dosyası düzenli olarak oluşur ama bozuktur, boştur veya eksik veri içerir. Fark edilmesi için bir felaket gerekir. Bu yazıda MariaDB için basit ama sağlam bir düzen kuracağız.

Mantıksal yedek nedir?

mysqldump (MariaDB'de mariadb-dump ismiyle de bulunur) veritabanını, yeniden oluşturan SQL komutları olarak dışa aktarır. Küçük ve orta ölçekli veritabanları (birkaç GB'a kadar) için en pratik yöntemdir. Çıktı bir metin dosyasıdır; sıkıştırılır, başka makineye kopyalanır, sürümler arası taşınabilir.

Çok büyük veritabanlarında veya saniye bazında kurtarma gerektiğinde fiziksel yedek (mariabackup) ve binlog tabanlı noktaya geri dönüş gerekir. Bu yazının kapsamı dışındadır.

1. Yedek için ayrı, kısıtlı bir kullanıcı

Yedeği root ile almak gereksiz risktir. Yalnızca okuma yetkisi olan bir kullanıcı oluşturun:

CREATE USER 'yedek'@'localhost' IDENTIFIED BY 'guclu-bir-parola';
GRANT SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT ON uygulama_db.* TO 'yedek'@'localhost';
FLUSH PRIVILEGES;

Parolayı komut satırına yazmak yerine ~/.my.cnf içinde tutun ve izni kısıtlayın:

[client]
user=yedek
password=guclu-bir-parola
chmod 600 ~/.my.cnf

Komut satırına yazılan parola ps çıktısında diğer kullanıcılara görünür; bu dosya yöntemi bunu engeller.

2. Yedekleme betiği

/usr/local/bin/db-yedek.sh:

#!/usr/bin/env bash
set -euo pipefail

DB="uygulama_db"
DIZIN="$HOME/yedekler"
TARIH="$(date +%Y%m%d_%H%M%S)"
DOSYA="$DIZIN/${DB}_${TARIH}.sql.gz"
SAKLA_GUN=14

mkdir -p "$DIZIN"

# --single-transaction: InnoDB tablolarını kilitlemeden tutarlı kopya alır
mariadb-dump --single-transaction --routines --events "$DB" | gzip -9 > "$DOSYA.gecici"

# Dosya sıkıştırma açısından sağlam mı?
gzip -t "$DOSYA.gecici"
mv "$DOSYA.gecici" "$DOSYA"

# Eski yedekleri sil
find "$DIZIN" -name "${DB}_*.sql.gz" -mtime +"$SAKLA_GUN" -delete

echo "TAMAM: $DOSYA ($(du -h "$DOSYA" | cut -f1))"

Dikkat edilecek noktalar:

  • set -euo pipefail sayesinde herhangi bir adım hata verirse betik durur. pipefail olmadan mariadb-dump çökse bile gzip başarılı döner ve boş bir yedek "başarılı" görünür.
  • Dosya önce .gecici adıyla yazılır, test edilir, sonra asıl adına taşınır. Yarım kalmış bir dosya yedek gibi görünmez.
  • --single-transaction yalnızca InnoDB tablolarında tutarlılık sağlar. MyISAM tabloları varsa kilitleme gerekir.
sudo chmod +x /usr/local/bin/db-yedek.sh

3. systemd timer ile zamanlama

/etc/systemd/system/db-yedek.service:

[Unit]
Description=Veritabani yedegi

[Service]
Type=oneshot
User=pi
ExecStart=/usr/local/bin/db-yedek.sh

/etc/systemd/system/db-yedek.timer:

[Unit]
Description=Her gece veritabani yedegi

[Timer]
OnCalendar=*-*-* 03:15:00
Persistent=true
RandomizedDelaySec=120

[Install]
WantedBy=timers.target

Persistent=true, cihaz o saatte kapalıysa açıldığında kaçırılan çalıştırmayı telafi eder. Cron'da bu yoktur. Etkinleştirin:

sudo systemctl daemon-reload
sudo systemctl enable --now db-yedek.timer
systemctl list-timers db-yedek.timer

İlk denemeyi beklemeden sudo systemctl start db-yedek.service ile yapın ve journalctl -u db-yedek ile sonucu görün.

4. Yedeği başka yere kopyalayın

Yedek, veritabanıyla aynı diskte duruyorsa disk bozulduğunda ikisi birlikte gider. En az bir kopyayı başka bir cihaza taşıyın. rsync ile SSH üzerinden:

rsync -a --delete-after "$HOME/yedekler/" kullanici@baska-makine:/yedekler/uygulama/

Bu konunun mantığı 3-2-1 yedekleme kuralı yazımızda anlatılıyor.

5. Geri yükleme testi: asıl önemli adım

Ayda bir, yedeği ayrı bir test veritabanına yükleyip kayıt sayısına bakın:

mariadb -e "CREATE DATABASE IF NOT EXISTS test_geri_yukle"
gunzip -c ~/yedekler/uygulama_db_20261004_031500.sql.gz | mariadb test_geri_yukle
mariadb -e "SELECT COUNT(*) FROM test_geri_yukle.hareket"
mariadb -e "DROP DATABASE test_geri_yukle"

Sayı üretimdeki tabloyla (yedek saatine göre) tutarlıysa yedeğiniz gerçektir. Bu testi takvime yazın; "yaparım" demek yetmez.

Kontrol listesi

  • Yedek kullanıcısı yalnızca gerekli yetkilere sahip.
  • Parola ~/.my.cnf içinde ve izni 600.
  • pipefail açık, geçici dosya adı kullanılıyor.
  • Timer Persistent=true.
  • Bir kopya başka cihazda.
  • Geri yükleme testi takvimde.
  • Yedekte kişisel veri varsa saklama süresi ve erişim yetkisi belirlenmiş (bkz. KVKK yazımız).
Not: Komutları üretim ortamında çalıştırmadan önce yedek alın ve önce test ortamında deneyin. Bir adım sizde farklı davranıyorsa bize yazın, rehberi güncelleyelim.