Teknoloji

Uygulama‑Tutarlı Yedekler Nasıl Alınır? LVM Snapshot ve fsfreeze ile MySQL/PostgreSQL’i Üşütmeden Dondurmak

Hikâyeyle Başlayalım: Disk Işığı, Gece Sessizliği ve O Anki Kalp Çarpıntısı

Hiç başına geldi mi? Gece ofiste tek başınasın, sunucunun üzerindeki o minik disk ışığı ritmini tutturmuş, arada bir daha hızlı yanıp sönüyor. Tam kahveni yudumlayacakken bir uyarı düşüyor: “Üretimde bir tablo yanlışlıkla güncellendi, geri almamız lazım.” O an içini küçük bir ürperti kaplıyor. Yedeğin var, evet; ama o yedek, uygulamanın gözünden bakınca gerçekten tutarlı mı? Veritabanının hafızasındaki işlemler diskle aynı noktada mı? İşte tam burada “uygulama‑tutarlı” yedek ile “çökme tutarlı” yedek arasındaki fark hayati oluyor.

Bu yazıda, LVM snapshot ve fsfreeze kullanarak MySQL ve PostgreSQL üzerinde sıcak, yani sistem çalışırken yedek almanın yolunu, adım adım ve içimizi ferahlatacak şekilde anlatmak istiyorum. Mesela şöyle düşün; sistem nefes alıp vermeyi kesmeden, ama o bir saniyelik fotoğraf karesi pırıl pırıl netsin istiyoruz. İşin sihri de burada. Bir yandan komutlar ve küçük hileler, bir yandan da sahada işe yarayan pratikler. Yazının sonunda, yalnızca nasıl snapshot alacağını değil, alınan yedeği nasıl güvenle geri döndüreceğini ve süreci nasıl otomatikleştireceğini de netleştirmiş olacağız.

Neden Uygulama‑Tutarlı? O İnce Çizgiyi Konuşalım

Bir dosya sistemini anlık görüntüyle yakaladığında, bazen fotoğrafta göz kırpan biri çıkar. Veritabanları da öyle; bellek ve disk arasında anlık bir trafik var. Sadece disk seviyesinde “çökme tutarlı” bir görüntü almak, sistem sanki ani elektrik kesilmiş gibi kabul edilebilir; ama transaction içindeki bir kayıt, uygulamanın beklediği sırayla yazılmamış olabilir. Bu da geri döndüğünde küçük sürprizlere yol açar. Kimi zaman loglarla toparlanır, kimi zaman toparlanmaz. Uygulama‑tutarlı yedek ise, veritabanının “tamam, şimdi poz veriyorum” dediği andır. MySQL’de kilitleyip temiz bir noktada dondurmak, PostgreSQL’de backup başlatıp dosya sistemini dondurmak gibi ufak ama kritik hamlelerle o pozu yakalarız.

Avantajı çok net: Geri dönüşte daha az ter, daha az nefes kesilmesi ve daha hızlı ayağa kalkma. Dezavantajı mı? Sahneyi kurmak için küçük bir koreografi gerekiyor. Öyle saniyelerle yarıştığımız bir dans, ama sahne ışıkları doğru ayarlanırsa kimse fark etmeden perde kapanıp açılıyor. Üstelik iyi bir planlamayla bu küçük dondurma anı, kullanıcıların fark etmeyeceği kadar kısa sürer.

LVM Snapshot’ın Kalbi: COW Mantığı, Küçük Pencereler ve Dikkat Puanları

LVM snapshot’ı, çalışan bir logical volume’un anlık fotoğrafını alır. Arkadaki büyü, copy‑on‑write denen mantıktır. Özetle şunu yapar: Sen fotoğrafı çektikten sonra veriler değişmeye devam eder ama snapshot güçlü bir hafızaya sahiptir; değişecek blokları kendi alanına kopyalar, böylece fotoğrafın bozulmaz. Bu yüzden snapshot için ayırdığın alan çok önemlidir. Eğer bu alan dolar da taşarsa, fotoğraf bulanıklaşır, yedek bozulur. O yüzden çektiğin resmi hızlıca başka bir yere kopyalamak ve snapshot’ı uzun süre açık bırakmamak iyi bir alışkanlıktır.

Bir başka küçük not: Veritabanı dizininin mümkünse kendi logical volume’u üzerinde olması işleri tatlılaştırır. Böylece yalnızca gerektiği yeri dondurur, sistemi komple durdurmazsın. XFS veya ext4 gibi dosya sistemleriyle fsfreeze güzel çalışır. Root dosya sistemini dondurmak gibi cesur hamlelerden uzak dur, yoksa kendi ayağına basmış olursun. Ayrıca snapshot alırken I/O’ya ufak bir maliyet biner; fotoğraf çekmek bedava değil ama doğru boyutlandırmayla hissedilmez hale gelir.

Komut tarafında en temel hareket şudur: var olan bir LV’nin snapshot’ını almak. Mesela veritabanı dizinin “vg0/data” adlı bir LV’de olduğunu varsayalım. O fotoğrafı şöyle çekersin:

lvcreate -s -L 10G -n data_snap /dev/vg0/data

Buradaki 10G snapshot için ayrılmış alanı anlatır. Büyüklüğünü, sistemde beklenen yazma trafiğine ve snapshot’ı ne kadar süre açık tutacağına göre seçersin. Snapshot alınır alınmaz onu ayrı bir noktaya read‑only olarak bağlayıp, kopyanı alıp, sonra snapshot’ı silmek en temiz akış.

fsfreeze: Düğmeye Bas, Kıpırdama; İşimiz Bitince Devam

fsfreeze, dosya sistemine “bir saniyecik bekler misin” der. O kısa esnada yazma işlemleri askıya alınır, dosya sistemi sabitlenir. Gerçekten buz kesmez ama hareketi durdurur. Biz de bu arada LVM snapshot’ı çat diye alırız. Sonra buzları çözer, hayat kaldığı yerden akar. Önemli olan o pencereyi kısa tutmak. Çünkü bu kısa bekleme anında yazmaya çalışan uygulamalar kuyruğa girer. Kısa tutarsan sorun değil, kimse fark etmeyecek.

fsfreeze komutu basit görünür ama etkisi büyük. Mount noktasını bilmen yeterli:

# Dondur
fsfreeze -f /var/lib/mysql

# Çöz
fsfreeze -u /var/lib/mysql

Detaylarına merak edenler için kılavuz sayfası gayet açıklayıcı; merak edersen fsfreeze ile ilgili bu belgeyi bir kenara açabilirsin. Ufak bir uyarı; container içindeysen, altındaki dosya sisteminin gerçekten dondurulabilir olduğundan emin ol. Bazen overlay veya ağ dosya sistemleri bu işi sevmez. Çözüm, en alttaki gerçek mount noktasında çalışmak ya da işin snapshot kısmını host seviyesinde yönetmek.

MySQL’de Sıcak Yedek: Kilitle, Dondur, Fotoğrafı Çek, Devam

MySQL tarafında amaç, o kareyi uygulamanın onayıyla yakalamak. InnoDB kullandığını varsayalım. Uygun bir an yaratmak için kısa süreli bir kilit kullanırız. Bu, uzun sürmeyecek ve genelde hissedilmeyecek. Akış şöyle düşünebilirsin: MySQL’e “bir an dur, nefes al” deriz, dosya sistemini dondururuz, snapshot’ı alırız, hemen çözüp devam ettiririz.

Örnek akış, root ya da gerekli yetkilere sahip bir kullanıcıyla:

# 1) MySQL'e bağlan ve yazıları kilitle
mysql -e "FLUSH TABLES WITH READ LOCK; FLUSH LOGS;"

# 2) Dosya sistemini dondur (örnek mount: /var/lib/mysql)
fsfreeze -f /var/lib/mysql

# 3) Snapshot'ı al
lvcreate -s -L 10G -n mysql_snap /dev/vg0/mysql

# 4) Dosya sistemini çöz
fsfreeze -u /var/lib/mysql

# 5) MySQL'de kilidi bırak
mysql -e "UNLOCK TABLES;"

Bu kadar. Artık snapshot’ını /dev/vg0/mysql_snap olarak görürsün. Bunu read‑only bağlayıp, güvenli bir dizine kopyalayabilirsin. Kopyalama için rsync ile sadece okuyarak aktarmak iyi bir pratik. Snapshot’ı bağlamak için:

mkdir -p /mnt/mysql_snap
mount -o ro /dev/vg0/mysql_snap /mnt/mysql_snap
rsync -aH --numeric-ids /mnt/mysql_snap/ /mnt/backup/mysql-$(date +%F)/
umount /mnt/mysql_snap
lvremove -y /dev/vg0/mysql_snap

Eğer binary log tutuyorsan ve logları yedeklemenin bir parçası yaptıysan, nokta atışı zamanda geri dönüş ihtimalin artar. Bu arada MySQL’in farklı sürümlerinde “LOCK INSTANCE FOR BACKUP” gibi daha “backup dostu” kilitleme seçenekleri de var. Detaylarında boğulmak istemeyenler için özet şu: Kilit kısa sürsün, snapshot hızlı alınsın, snapshot hemen kopyalansın. İstersen MySQL’in yedekleme yöntemlerine genel bakışı buradan göz atıp, kullandığın sürüme uygun komutu seçebilirsin.

Bir ufacık not daha: Datadir’in ve ib_logfile gibi kritik dosyaların aynı LV’de olmasına dikkat. Parçalı mimarilerde her parça için aynı anda snapshot gerekebilir, bu yüzden tasarımı sade tutmak işini kolaylaştırır. İşin güzel tarafı, doğru uygulandığında bu yöntem üretimde kullanıcıların fark etmeyeceği kadar kısa bir anı kaplıyor.

PostgreSQL’de Sıcak Yedek: Backup Başlat, Dondur, Snapshot, Bitir

PostgreSQL biraz farklı bir kural seti istiyor. O da poz vermek istiyor ama “bana haber ver” diyor. Kısaca şunu yaparız: “Backup’ı başlat” komutunu çalıştırırız, dosya sistemini dondurur, snapshot’ı alır, dosya sistemini çözer, “backup bitti” deriz. Bu akış sırasında WAL dosyalarının tamamlığını da garanti altına almak için arşivlemeyi açık tutmak akıllıca. Böylece snapshot’tan dönerken aradaki hareketleri WAL’lerden yakalar, eksik bir kare kalmaz.

Ön koşullar çok karmaşık değil. postgresql.conf içinde wal_level’in en azından replica, archive_mode’un on, archive_command’ın da gerçekçi bir hedefe yazıyor olması güzel bir başlangıç. Sonrası akış:

# 1) Backup oturumunu başlat (psql içinde):
SELECT pg_backup_start('lvm-snapshot', true);

# 2) Dosya sistemini dondur (örnek mount: /var/lib/postgresql/15/main)
fsfreeze -f /var/lib/postgresql/15/main

# 3) Snapshot'ı al
lvcreate -s -L 10G -n pgdata_snap /dev/vg0/pgdata

# 4) Dosya sistemini çöz
fsfreeze -u /var/lib/postgresql/15/main

# 5) Backup'ı bitir (psql içinde):
SELECT pg_backup_stop();

Ardından snapshot’ı read‑only bağlar, güvenli bir dizine kopyalarsın. Bu esnada WAL arşivinin de akmaya devam ettiğinden emin olmak, restore anında eksiksiz toparlama sağlar. PostgreSQL’in dosya kopyalama temelli yedekleme önerileri net; ayrıntı merak edenler için resmi belgedeki dosya sistemi yedeği bölümü birebir bu akışı tarif eder. Mesela şöyle düşünün; bir film sahnesi çekiyorsun, yönetmen “kestik” diyor, kameraman freeze tuşuna basıp bir kare yakalıyor, sonra devam. İşte bu kadar doğal.

Bir önemli ayrıntı daha var. Eğer tablespace’leri ayrı L’Vlere dağıttıysan, hepsini aynı anda dondurup aynı anda snapshot almak gerekebilir. En sağlıklısı, PGDATA ve varsa tablespace’lerin aynı volume grubu içinde ve senkronize snapshot alabilecek şekilde tasarlanması. Bu planlamayı başta yaparsan, sahnede zihin karışıklığı yaşamazsın.

Geri Dönüşü Şimdiden Düşün: Snapshot’tan Restore ve Prova

Yedek almak güzel de, onu döndüreceğin günü de düşünmek gerekir. Bu yüzden ben genelde haftada en az bir kez “prova restore” yaparım. Üretimle aynı sürümde bir test sunucusu ayırır, alınan snapshot’tan kopyalanan yedeği oraya kurar, uygulamayı ayağa kaldırırım. Sürprizler sahnede değil prova odasında kalsın diye.

MySQL’de dönüş genelde şu şekilde olur: Yedek dizinini yeni bir sunucuda datadir olarak yerleştirirsin, izinleri ve kullanıcıyı düzeltirsin, my.cnf içindeki yolları doğrular, sonra MySQL’i başlatırsın. Eğer binary log’larla noktaya dönüş yapacaksan, snapshot noktasındaki position’ı işaret eden notlarını referans alırsın. PostgreSQL’de ise recovery tarafında WAL’leri sağlayacak şekilde restore_command ayarlarsın, recovery.signal dokunursun, sonra başlatırsın. Sistem WAL’leri çektikçe o anki kareye doğru kendini tamamlar.

Basit bir rsync ile restore kopyasını almak bile çoğu zaman yeterli. Yeter ki hedef dizini doğru bağla, izinleri düzelt, servisleri başlatmadan önce konfigürasyonları gözden geçir. Kulağa çok klişe geliyor ama “backup’ı al, restore et, doğrula” üçlüsü en iyi dostundur. Prova yaptıkça gerçek hayattaki stres düzeyi düşer ve karar anlarında bile elin titremez.

Otomasyon, Zamanlama ve Anı Yakalama: Küçük Script, Büyük Huzur

Bir süre sonra bu işi elle yapmak yerine bir script ve zamanlayıcıya bağlamak isteyeceksin. İşin püf noktası, hatayı gördüğünde zarifçe geri sarabilmesi. Mesela MySQL akışında, kilit atıldıktan sonra herhangi bir adım başarısız olursa fsfreeze çözülmeli, kilit bırakılmalı. PostgreSQL akışında, backup başlatıldıktan sonra snapshot başarısızsa backup’ı durdurmayı unutmamalı. Denetimi sıkı ama kısa tutan bir script, günün sonunda sana saatler kazandırır.

Örnek bir MySQL script’inin iskeleti şöyle olabilir; fikir versin, birebir kopyalamadan önce mutlaka kendi yollarına ve koşullarına göre düzenle:

#!/bin/bash
set -euo pipefail
MYSQL_MNT="/var/lib/mysql"
LV_SRC="/dev/vg0/mysql"
SNAP_NAME="mysql_snap_$(date +%F-%H%M%S)"
SNAP_LV="/dev/vg0/${SNAP_NAME}"
BACKUP_DIR="/mnt/backup/mysql-$(date +%F-%H%M%S)"
cleanup() { fsfreeze -u "$MYSQL_MNT" || true; mysql -e "UNLOCK TABLES;" || true; }
trap cleanup EXIT
mysql -e "FLUSH TABLES WITH READ LOCK; FLUSH LOGS;"
fsfreeze -f "$MYSQL_MNT"
lvcreate -s -L 10G -n "$SNAP_NAME" "$LV_SRC"
fsfreeze -u "$MYSQL_MNT"
mysql -e "UNLOCK TABLES;"
mkdir -p "$BACKUP_DIR"
mount -o ro "$SNAP_LV" /mnt/snap
rsync -aH --numeric-ids /mnt/snap/ "$BACKUP_DIR/"
umount /mnt/snap
lvremove -y "$SNAP_LV"

Benzer bir iskeleti PostgreSQL için de kurarsın. Orada psql ile pg_backup_start/stop çağrılarını koyar, freeze ve snapshot arasına alırsın. Günün sonunda bu script’i systemd timer ile her gece çalıştırır, log’ları da merkezi bir yere akıtırsın. Eğer uzak depolamaya göndereceksen, rsync sonrası rclone ile bir obje depolamaya, ya da SFTP ile uzak bir kasaya aktarmak iyi bir plan. Bu noktada felaket dayanıklılığına geniş açıdan bakmak istersen, replikasyon ve DNS yönlendirmesiyle kombinlediğim bir yazıda tüm resmi toparlamıştım; merak edersen çok bölgeli mimariler ve felaket dayanıklılığı kısmına bakabilirsin.

Sık Yapılan Hatalar ve Tatlı Uyarılar

En sık gördüğüm aksaklık, snapshot alanının küçük bırakılması. Fotoğraf çekiyorsun, objektifin kapağı bir anda düşüyor gibi düşün; yer dolunca COW tutmuyor. Bu yüzden beklediğin yedek süresi ve o süre boyunca yazma hızına göre yeterli alan ayır. Bir diğeri, uzun süre snapshot’ı unutup bırakmak. Snapshot, kalıcı yedek değil; anı yakalaman için bir araç. Çek, kopyala, kaldır. Üç adımı hızlı uygula.

Bir başka sıkıntı, dosya sistemini dondurduğunu sanıp aslında farklı bir mount noktasında çalışmak. Özellikle container kökenli dağıtımlarda bu karışabiliyor. İşleme başlamadan önce “bu dizin nereye mount edilmiş” sorusuna cevap ver. Bir de şu var: PostgreSQL’de backup başlatmayı unutanlar, sonradan WAL bulamayınca eksik kareyle kalıyor. Komut dizini kısa ama net yaz, her adımdan sonra minimal kontrol koy. Küçük hatalar, büyük gecelere dönüşmesin.

Ek Okumalarla Ufku Genişlet

Elinin altında iki kapı daha olsun istiyorsan, biri PostgreSQL’in dosya temelli yedek anlatımı, diğeri MySQL’in kendi önerileri. fsfreeze komutunun davranışını daha derinden merak edersen kılavuz sayfası hem kısa hem öz. Şöyle kenara iliştiriyorum: PostgreSQL dosya sistemi yedeği ve MySQL yedekleme yöntemleri. fsfreeze için de kılavuz sayfasına bakmak çoğu soruyu dağıtır. Linkleri arada açıp kaparsın, kafana takılan her noktaya küçük bir spot ışığı tutarlar.

Kapanış: Sahne Işıkları Sönmeden Son Bir Derin Nefes

Toparlayalım. Uygulama‑tutarlı yedek dediğimiz şey, veritabanına “şimdi poz ver” dedirtebilmek. MySQL’de kısa bir kilit ve log temizliği, PostgreSQL’de backup başlangıç/bitiş sinyalleri, dosya sisteminde fsfreeze ile ufak bir duruş ve LVM snapshot ile kareyi yakalama. Hepsi doğru sırayla olunca, geri dönüşte ter dökmeden ayağa kalkarsın. İşin şifresi, anı uzatmamak, snapshot alanını doğru boyutlamak, yedeği hızlıca güvenli bir yere taşımak ve düzenli prova yapmaktır.

Eğer bu akışı bir script ve zamanlayıcıyla süsler, hata durumlarını kibarca ele alırsan, geceleri sunucu başında beklemek yerine kahveni sakin içersin. Benim rutinim şöyle: Her gece otomatik sıcak yedek, haftada bir prova restore, ayda bir de tam bir geri dönüş simülasyonu. Küçük adımlar, büyük huzur. Umarım bu anlatım sana ilham verir ve ilk snapshot yedeğini attığında o küçük disk ışığına gülümseyerek bakarsın. Sorularını not al; bir dahaki yazıda belki replikasyonla snapshot’ı birlikte ele alır, daha da sağlam bir sahne kurarız. Şimdilik benden bu kadar, görüşmek üzere.

Sıkça Sorulan Sorular

fsfreeze çok kısa sürerse kimse fark etmez. Sadece hedef mount noktasındaki yazmalar beklemeye alınır. Snapshot’ı hızlı alır, hemen çözüp devam edersen akış pürüzsüz olur.

Ne kadar kısa, o kadar iyi. Snapshot alanı dolarsa fotoğraf bozulur. Genelde hemen bağlayıp kopyalamak ve ardından snapshot’ı silmek en güvenli yoldur.

Çoğu zaman riskli olur. Backup başlangıç/bitiş çağrıları, gerekli WAL’lerin saklanmasını sağlar. Unutursan restore sonrası eksik kareler yüzünden toparlamak zorlaşır.