
Veri tabanı sistemlerinin en temel ve en önemli özelliklerinden biride hata durumlarında sizi koruyacak bir yedekleme politikasına sahip olmasıdır. Veritabanı herhangi bir nedenden dolayı crash olduğunda veya veritabanı geçmiş bir andaki haline döndürülmek istendiğinde veritabanı backup/restore işlemleri kullanılır. PostgreSQL veri tabanında temelde üç tip backup/restore operasyonu mevcuttur.
- Logical Backup
- Sql Dump (pg_dump ve pg_dumpall)
- Copy Komutu (CSV Load , Unload)
- File System level Backup (Cold Backup, Offline Backup)
- Online Backup (Continuous Archiving)
- pg_basebackup
- pgBackRest (extension)
Geçen yazımızda Logical Backup kavramlarını işlemiştik. POSTGRESQL YEDEKLEME VE KURTARMA -1 (BACKUP AND RECOVERY) LOGICAL BACKUP – FARUK ÇEVİK BLOG (farukcevik.com.tr) Burada ise COld Backup ve Online Backup kavramları ile devam edeceğiz.
2. File System level Backup (Cold Backup)
İsminde bulunan File System Cold vs bunlara bakmayın arkadaşlar oldukça basit veritabanının tüm dosyalarının kopyalanması işlemidir, bu işlemin geçerli ve tutarlı olabilmesi için veritabanının mutlaka kapalı olması gerekmektedir. Günümüzde sadece belli operasyonlar için kullanılıyor, Veritabanın kapatılması durumu ayrıca restore durumunda backup alınan noktaya dönülmesi gibi durumlar kabul edilebilir bir durum değildi bu yüzden bu bir backup stratejisi olarak kullanılması düşünülemez.
Örnek olarak veritabanımızı farklı bir disk alanına taşıyor olalım bu durumda bu yöntemi kullanabiliriz, veritabanı kapatılır, Cold backup alınır , yeni dizine taşınır ardından postgresql.conf parametreleri yeni dizine göre düzenlenir ve bu dizin gösterilerek veritabanı açılır.
tar -cvf /backup/cold_backup.tar /postgres/14/data
Tüm veritabanımız cold_backup.tar dosyasının içerisindedir. Burada dikkat edilmesi greken bir nokta bulunmakltadır, Centos Redhat tabanlı ve initdb ile kurulan veritabanlarında tüm konfigürasyon dosyaları $PGDATA altında gelmektedir, ayrıca ayrı bir dizine veya disk alanına bir tablespace alanı oluşturulmuş ise bu tablespace dizinide tar içerisine dahil edilmelidir.
3.Online Backup (Continuous Archiving)
Hot Backup, veri tabanı çalışmaya devam ederken ve kullanıcılar canlı sistemde işlemlerini sürdürürken alınan bir yedek türüdür, bu yedeğin tutarlı (consistent) olabilmesini sağlayan ise daha önce açıkladığımız WAL (Write Ahead Logging) kavramıdır, veritabanın tutarlı yedeklerinin alınabilmesi için veritabanında archive modun açık olması yani WAL dosyalarını belirlediğimiz dizine arşivleyen archiver prosessinin çalışıyor olması gerekmektedir. Hot backup almanın postgresql deki varsyalın yolu pg_basebackup tır.
Yaygın kullanım şekli belli aralıklarla schedule (çalışma programı) yapılır , örneğinde her gece 00:00 da pg_basebackup ile yedek alınır, bu işlem ise genelde Linux crontab üzerinden yapılır. Bu duruma göre Gece 00:00 da alınan bir backup var elimizde peki veritabanımız öğleden sonra saat 16:00’da crash oldu ve backuptan dönmek (restore- recover) ihtiyacı hasıl oldu, bu durumda elimizdeki backup kullandığımızda gece 00:00’a döneriz fakat 16 saat lik bir fark var bu zaman dilimde veritabanı üzerinde meydana gelen değişimler ne olacak, archive mode açık ise bu değişimlerin tamamı belirtilen archive dizininde mevcuttur, ayrıca archive olmamış WAL varsa oda problem değil, WAL dosyaları da pg_wal dizininde mevcut olduğuna göre hiç bir problem yok 0 veri kaybı ile bu veritabanını restore – recover işlemlerini gerçekleştirebiliriz.
Archive mode on yapmak (varsayılanda kapalıdır) ve veritabanının online backuplarını tutarlı alabilmek için bazı parametre ayarlarının yapılması bazılarınında kontrol edilmesi gerekmektedir. Bunlar nelerdir?
wal_level : Wal dosyalarında tutulacak bilgi seviyesini belirler, varsayılanı replica dır, bu hot backup almak archive dan restore yapabilmek ve stream replica oluşturmak için yeterli bilgi düzeyini içerir. üç değer alabilir, {minimal,replica,logical} en düşük seviye adından da anlaşılacağı üzere minimal dır en geniş kapsamlı bilgi düzeyi ise logical dır.
archive_mode varsayılan değer off dur ve kapalıdır , açılması gerekmektedir. on yapılmalıdır, bu değeri on olarak açıyorsak archive_command parametresine de komutu vermeliyiz.
postgresql.conf için
archive_mode = on
veya
ALTER SYSTEM SET archive_mode = on;
archive_command archive alınacağı zaman hangi komutun çalıştıracağını bu parametre ie veririz, postgresql.conf dosyasından veya alter system komutları ile bu dizinleri verebiliriz.
- Unix:
archive_command= ‘cp –i %p /postgres/archivedir/%f </dev/null’
- %f benzersiz unique dosya isimleri oluşmasını sağlar.
- %p, WAL’ın mutlak yoludur
postgresql.conf
archive_command = 'test ! -f /postgres/archive/%f && cp %p /postgres/archive/%f'
veya, psql den
alter system set archive_command = 'test ! -f /postgres/archive/%f && cp %p /postgres/archive/%f';
Yukarıda yaptığımız değişikliklerin aktif olabilmesi için veritabanın kapatılıp açılması gerekmektedir, restart gerektiğini pg_settings tablosunu sorgulayarak pending_restart durumundan görebiliriz “t” true ise, restart bekliyor demektir.
postgres=# select * from pg_settings where name='archive_mode';
-[ RECORD 1 ]---+-----------------------------------------------------
name | archive_mode
setting | off
category | Write-Ahead Log / Archiving
short_desc | Allows archiving of WAL files using archive_command.
enumvals | {always,on,off}
pending_restart | t
Veritabanını kapatıp açalım;
$ pg_ctl stop
$ pg_ctl start
postgres=# select * from pg_settings where name='archive_mode';
-[ RECORD 1 ]---+-----------------------------------------------------
name | archive_mode
setting | on
category | Write-Ahead Log / Archiving
short_desc | Allows archiving of WAL files using
enumvals | {always,on,off}
pending_restart | f
pg_basebackup İle Backup Almak
pb_basebackup ile online backup lar alınabilir, alınan backup ile tam geri yüklememe (full restore ve recovery) yapılabilirken, hemde belirli bir zaman geri yükleme diğer adıyla Point In Time Recovery (PITR) yapılabilir. pg_basebackup tüm cluster dizinin alır ve cluster düzeyinde bir tam backup alır, pg_basebackup ile tekbir veritabanının veya herhangi bir objenin yedeği alınamaz, eğer böyle bir ihtiyaç varsa pg_dump ve pg_dumpall kullanılabilir.
pg_basebackup aynı zamanda replica oluşturmak için kullanılır ve user yetkisi gerektirir, pg_basebackup ile backup alacak user ya superuser olmalıdır yada replikasyon yetkisine sahip bir user olmalıdır aynı zamanda pg_hba.conf dosyasında gerekli izinlerin de verilmiş olması gerekmektedir.
pg_basebackup işlemi veritabanı sunucusu üzerinde I/O yükü oluşturacaktır, aynı anda birden fazla pg_basebackup prosesi çalıştırılabilir ancak I/O darboğazı riski göz önüne alınmalıdır.
pg_basebackup uzak sunucu üzerinden çağrılabilir, uzak sunucu üzerine network üzerinden doğrudan backup alınabilir, aynı zamanda stream replica sunucular üzerinden de pg_basebackup ile yedek alınabilir,stream replica ve cascade stream replica konularında bu konu ayrıca anlatılacaktır.
pg_basebackup –help diyerek pg_basebackup syntax yapısını ve tüm option larını görebilirsiniz
$ pg_basebackup --help |
Önemli Optionlarını inceleyelim;
- -D : Yedek alınacak dizini adresler
- -l : alınan yedeği etiketler
- -P : yedekleme işleminin sürecini % olarak raporlar.
- -F : Formatı belirler, p (plain) DATA dizinini olduğu gibi belirtilen dizine kopyalar, t (tar) tar formatında belirtilen dizine DATA dizinini kopyalar.
- -z : -t option ile tar olarak alınan yedekleri gip ile sıkıştırır, -Z ile sıkıştırma oranı 0-9 arasında bir seviyede verilebilir.
- -c : fast checkpoint çalıştırır. Eğer bu option kullanılmaz ise pg_basebackup çalıştırıldığında ilk checkpoint gerçekleşene kadar bekler, checkpoint sonrası backup almaya başlar bu parametre kullanılarak pg_basebackup başlamadan hemen önce checkpoint fast çalışır ve hemen pg_basebackup çalışmaya başlar.
- -X WAL dosyalarının yedeklenmesi ile ilgili methodu belirler, n (none) WAL dosyaları yedeklenmez, f (fetch) WAL dosyalarını yedekleme bittikten sonra yedekler, burada yedekleme uzun sürmesi durumunda WAL dosyalarının silinmesini engellemek için wal_keep_size parametresini yeterli büyüklükte ayarlamak gerekir. Yedek tamamlanmadan kaynakta WAL dosyaları ezilirse yedek tutarsız olur ve kullanılamaz s (stream) , yedek başladıktan sonra 2. bir bağlantı açılır yedekleme sırasında paralel olarak WAL dosyaları stream olarak ilgili dizine alınır, tar ile alınırsa pg_wal.tar olarak yedeklenir.
- -T : tablespace mapping yapar, klasörünü yeniden konumlandırır. –tablespace-mapping=eski_tablspace=yeni_tablespace klasörü tam yolu girilmelidir, içi boş olmalıdır, tablespace yeni dizinlerine göre linkleride yeniden güncellenecektir.
- -v : verbose mod,detaylı log çıktısı alınmasını sağlar.
- Connection options:
- -d, –dbname=CONNSTR
- -h, –host=HOSTNAME
- -p, –port=PORT
- -s, –status-interval=INTERVAL
- -U, –username=NAME
- -w, –no-password
- -W, –password
Örnek bir backup alalım;
$ pg_basebackup -p 5434 -D /postgres/backup/backup_08012023 -c fast -Xf -z -Z 9 -l Full_backup -P -v -F tar &>>backup.log |
backup dizinine bakalım;
$ ls -lsh |
buradaki base.tar.gz $PGDATA (DATA) dizinimizin tamamıdır, ayrıca 16397.tar.gz de default tablespace ler dışında oluşturulmuş bir tablespace alanıdır ve 16397 bu tablespace in OID sidir. Tablespace leri bir kontrol edelim
postgres=# select * from pg_tablespace ; |
restore için base.tar dosyasını $PGDATA (DATA) dizini altında tardan çıkarmamız gerekmektedir, yine aynı şekilde tablespace ler ile ilgili tar dosyalarımızıda doğru dizinler altında tardan çıkarmamız yeterli olacaktır. Herhangi bir crash durumunda bunun birçok sebebi olabilir bu yedeklerden recover yapmak zorunda kalabiliriz.
Yedekten Geri Dönme (Full Recovery)
Veritabanı yedekten döneceğimiz zaman yeni bir sunucu üzerine yedekten geri dönüş yapacaksak (Full Recovery) İlgili dizinler doğru yetkiler ile öncesinde ayarlamamız gerekmektedir, bizim durumumuzda aynı sunucu üzerinde yedekten geri dönüş yapıyoruz, biz dizinlerimizi öncelikle temizleyelim, $PGDATA ve tablespace alanlarını içeren dizinler komple temizlenir.
$ pwd |
$PGDATA (data) dizini altına base.tar.gz dosyamızı gönderip tar dan çıkaralım , ayrıca tüm tablespace tar dosyalarını da kendi dizinlerine gönderek tar dan çıkaralım;
$ tar -xvf /postgres/backup/backup_08012023/base.tar.gz -C /postgres/14/data/ |
Tablespace ler için sembolik linkler oluşturulur;
$ ln -s /postgres/14/tablespaces /postgres/14/data/pg_tblspc/16397
Recovery modda başlatmak için $PGDATA altındaki recovery.signal dosyası oluşturulur ve standby.signal varsa dosyası silinir. Her iki dosya aynı anda bulunursa standby mode aktif olacaktır.
postgresql.conf dosyasına restore_command ve recovery_target_timeline parametreleri aktif edilir( latest). (PostgreSQL 12 versiyonundan önce bu parametreler recovery.conf dosyasında yapılmaktaydı). recovery_target parametresi recovery_target=’immediate’ olarak eklenirse consistent duruma erişir erişmez recover işlemi sonlandırılır ve veritabanı açılır.
$ touch /postgres/14/data/recovery.signal ##postgresql.conf içerisinde
|
Artık veritabanını yedekten başlatabiliriz;
$ pg_ctl -o '--config-file=/postgres/14/data/postgresql.conf' -D /postgres/14/data/ -l pg.log start |
pg_basebackup ile backup almayı ve bu backuptan nasıl kurtarma yapacağımızı yukarıdaki örnekte görmüş olduk, ancak her defasında el ile backup alamayacağımıza göre bu backupları zamanlanmış görev (schedule) olarak yapılandırmamız gerekmektedir, bunun için öncelikle backup için bir bash script hazırlamalıyız ve crontab ta bunu schedule yapmamız gerekmektedir.
Backupları bir dizine otomatik olarak aldırıyoruz, ancak backup aldığımız alan sonsuz büyüklükte değildir ve eski backupları ve eski archive dosyalarının belli aralıklarla temizlenmesi gerekmektedir, makul olan backup alma scriptinin içerisine backup alındıktan sonra eski backupları temizleyen bir bash eklemek olacaktır. Aşağıda örnek bir bash scripti verilmiştir.
#######################
## pg_basebackup.sh ##
#######################
. ~/.bash_profile
#--------- B-A-S-L-A-N-G-I-C ------#
BASE_DIRECTORY="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
BACKUP_DIR=/postgres/backup
LONG_SYSTEM_NAME=$(hostname -f)
SHORT_SYSTEM_NAME=$(hostname -a)
IP=$(hostname -i)
SISTEM_ADI="$DB_NAME GUNLUK FULL BACKUP"
#-------- B-I-T-I-S --------#
LOG_DIZINI=$BASE_DIRECTORY/backup_logs
mkdir -p $LOG_DIZINI
LOG_DOSYA=$LOG_DIZINI/pg_basebackup_$(date +%Y%m%d_%H%M).log
echo "LOG KONUMU : $LOG_DOSYA">>$LOG_DOSYA
echo "BASLANGIC ZAMANI: $(date +%d.%m.%Y\ %H:%M:%S)">>$LOG_DOSYA
BUGUN=$(date +%Y%m%d)
BACKUP_DIZINI=$BACKUP_DIR/DB_BACKUPS/$BUGUN
mkdir -p $BACKUP_DIZINI
chmod -R 775 $BACKUP_DIZINI
pg_basebackup -p 5434 -D $BACKUP_DIZINI -c fast -F tar -X fetch -z -Z 9 -l Full_$BUGUN -P -v &>>$LOG_DOSYA
echo "BITIS ZAMANI : $(date +%d.%m.%Y\ %H:%M:%S)">>$LOG_DOSYA
echo "">>$LOG_DOSYA
########### 1 AYDAN ESKI BACKUPLARI SILER ###########
find /postgres/backup/DB_BACKUPS/ -mtime +30 -exec rm -rf "{}" ";"
#######################################################
########### 1 AYDAN ESKI aRCHIVE DOSYALARINI SILER ###########
find /postgres/archive/* -mtime +30 -exec rm -f "{}" ";"
#######################################################
Crontab backup scriptimizi ekleyelim her gün gece 23:00 da çalışsın, postgres OS user ile crontab -e diyerek aşağıdaki satır crontab a ekenir ve kaydedilir.
00 23 * * * sh /postgres/backup/scripts/pg_basebackup.sh
Bu yazı oldukça uzadı o yüzden Point In Time Recovery ve PgBackrest konuları bir sonraki yazıda ele alınacaktır.
Bir yanıt yazın