{"id":1680,"date":"2025-11-11T15:18:51","date_gmt":"2025-11-11T12:18:51","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/vps-uzerinde-postgresql-yedekleme-ve-pitr-pgbackrest-ile-wal-arsivleme-adim-adim\/"},"modified":"2025-11-11T15:18:51","modified_gmt":"2025-11-11T12:18:51","slug":"vps-uzerinde-postgresql-yedekleme-ve-pitr-pgbackrest-ile-wal-arsivleme-adim-adim","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/vps-uzerinde-postgresql-yedekleme-ve-pitr-pgbackrest-ile-wal-arsivleme-adim-adim\/","title":{"rendered":"VPS \u00dczerinde PostgreSQL Yedekleme ve PITR: pgBackRest ile WAL Ar\u015fivleme Ad\u0131m Ad\u0131m"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Hic_Keske_Zamani_Geri_Alsam_Dedigin_Oldu_mu\"><span class=\"toc_number toc_depth_1\">1<\/span> Hi\u00e7 \u201cKe\u015fke Zaman\u0131 Geri Alsam\u201d Dedi\u011fin Oldu mu?<\/a><\/li><li><a href=\"#Neyi_Neden_Yaptigimizi_Bilerek_Baslayalim\"><span class=\"toc_number toc_depth_1\">2<\/span> Neyi, Neden Yapt\u0131\u011f\u0131m\u0131z\u0131 Bilerek Ba\u015flayal\u0131m<\/a><\/li><li><a href=\"#Ortami_Kuruyoruz_pgBackRest_PostgreSQL_ve_Yol_Haritasi\"><span class=\"toc_number toc_depth_1\">3<\/span> Ortam\u0131 Kuruyoruz: pgBackRest, PostgreSQL ve Yol Haritas\u0131<\/a><ul><li><a href=\"#Hangi_parcalara_ihtiyacimiz_var\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Hangi par\u00e7alara ihtiyac\u0131m\u0131z var?<\/a><\/li><li><a href=\"#pgBackRest_kurulumu\"><span class=\"toc_number toc_depth_2\">3.2<\/span> pgBackRest kurulumu<\/a><\/li><li><a href=\"#PostgreSQLi_WAL_arsivlemeye_hazirlamak\"><span class=\"toc_number toc_depth_2\">3.3<\/span> PostgreSQL\u2019i WAL ar\u015fivlemeye haz\u0131rlamak<\/a><\/li><\/ul><\/li><li><a href=\"#Ilk_Yedek_Tam_Sonra_Diferansiyel_WALler_Aksin\"><span class=\"toc_number toc_depth_1\">4<\/span> \u0130lk Yedek: Tam, Sonra Diferansiyel; WAL\u2019ler Aks\u0131n<\/a><\/li><li><a href=\"#PITR_Zamani_Geri_Sarmak_Nasil_Hissettirir\"><span class=\"toc_number toc_depth_1\">5<\/span> PITR: Zaman\u0131 Geri Sarmak Nas\u0131l Hissettirir?<\/a><ul><li><a href=\"#Hedef_zamani_belirlemek\"><span class=\"toc_number toc_depth_2\">5.1<\/span> Hedef zaman\u0131 belirlemek<\/a><\/li><li><a href=\"#Veritabanini_durdurmak\"><span class=\"toc_number toc_depth_2\">5.2<\/span> Veritaban\u0131n\u0131 durdurmak<\/a><\/li><li><a href=\"#pgBackRest_restore_komutu\"><span class=\"toc_number toc_depth_2\">5.3<\/span> pgBackRest restore komutu<\/a><\/li><\/ul><\/li><li><a href=\"#Kucuk_Ince_Ayarlar_Tutma_Politikasi_Sikistirma_Sifreleme\"><span class=\"toc_number toc_depth_1\">6<\/span> K\u00fc\u00e7\u00fck \u0130nce Ayarlar: Tutma Politikas\u0131, S\u0131k\u0131\u015ft\u0131rma, \u015eifreleme<\/a><\/li><li><a href=\"#Yedekleri_Duzenli_Test_Etmek_Runbook_Alarm_Kucuk_Provalar\"><span class=\"toc_number toc_depth_1\">7<\/span> Yedekleri D\u00fczenli Test Etmek: Runbook, Alarm, K\u00fc\u00e7\u00fck Provalar<\/a><\/li><li><a href=\"#Gercek_Hayattan_Kucuk_Dersler_Izinler_Saat_Dilimi_WAL_Taskini\"><span class=\"toc_number toc_depth_1\">8<\/span> Ger\u00e7ek Hayattan K\u00fc\u00e7\u00fck Dersler: \u0130zinler, Saat Dilimi, WAL Ta\u015fk\u0131n\u0131<\/a><\/li><li><a href=\"#Yapilandirmayi_Zenginlestirmek_Uzak_Repo_Ayri_Disk_Sistem_Servisleri\"><span class=\"toc_number toc_depth_1\">9<\/span> Yap\u0131land\u0131rmay\u0131 Zenginle\u015ftirmek: Uzak Repo, Ayr\u0131 Disk, Sistem Servisleri<\/a><\/li><li><a href=\"#Adim_Adim_Ozet_Akis_Kur_Dogrula_Yedekle_Test_Et\"><span class=\"toc_number toc_depth_1\">10<\/span> Ad\u0131m Ad\u0131m \u00d6zet Ak\u0131\u015f: Kur, Do\u011frula, Yedekle, Test Et<\/a><\/li><li><a href=\"#Sik_Karsilastigim_Sorular_ve_Kucuk_Notlar\"><span class=\"toc_number toc_depth_1\">11<\/span> S\u0131k Kar\u015f\u0131la\u015ft\u0131\u011f\u0131m Sorular ve K\u00fc\u00e7\u00fck Notlar<\/a><\/li><li><a href=\"#Kapanis_Bugun_Kucuk_Bir_Adim_Yarin_Buyuk_Bir_Rahatlik\"><span class=\"toc_number toc_depth_1\">12<\/span> Kapan\u0131\u015f: Bug\u00fcn K\u00fc\u00e7\u00fck Bir Ad\u0131m, Yar\u0131n B\u00fcy\u00fck Bir Rahatl\u0131k<\/a><\/li><\/ul><\/div>\n<h2 id='section-1'><span id=\"Hic_Keske_Zamani_Geri_Alsam_Dedigin_Oldu_mu\">Hi\u00e7 \u201cKe\u015fke Zaman\u0131 Geri Alsam\u201d Dedi\u011fin Oldu mu?<\/span><\/h2>\n<p>Bir sabah ofiste kahvemi koydum, terminali a\u00e7t\u0131m, g\u00f6z\u00fcm yar\u0131 uykulu bir migration komutunu \u00e7al\u0131\u015ft\u0131rd\u0131m. Son anda fark ettim ki, yanl\u0131\u015f veritaban\u0131nday\u0131m. Birka\u00e7 tabloyu u\u00e7urup, y\u00fcz\u00fcmde o malum donuk ifade ile kald\u0131m. \u201cKe\u015fke bir iki saat \u00f6ncesine d\u00f6nebilsem\u201d dedim. \u0130\u015fte tam burada <strong>PostgreSQL\u2019de PITR (Point-In-Time Recovery)<\/strong> ve <strong>pgBackRest<\/strong> sahneye \u00e7\u0131k\u0131yor. Zaman\u0131 geri almak gibi bir sihir de\u011fil belki, ama en az\u0131ndan veritaban\u0131n\u0131 belirli bir zamana geri d\u00f6nd\u00fcrmek m\u00fcmk\u00fcn. Bu yaz\u0131da, bir <a href=\"https:\/\/www.dchost.com\/tr\/vps\">VPS<\/a> \u00fczerinde s\u0131f\u0131rdan <strong>WAL ar\u015fivleme<\/strong> ve <strong>pgBackRest<\/strong> ile yedeklemeyi kurup <strong>PITR<\/strong> yapmay\u0131 ad\u0131m ad\u0131m anlataca\u011f\u0131m.<\/p>\n<p>Hedefimiz \u015fu: Basit ama sa\u011flam bir kurulum, anla\u015f\u0131l\u0131r bir yap\u0131land\u0131rma, d\u00fczenli yedekler ve gerekti\u011finde paniksiz bir geri d\u00f6n\u00fc\u015f. Komutlar\u0131 tek tek verece\u011fim, ama sakince, her ad\u0131m\u0131n nedenini konu\u015fa konu\u015fa gidece\u011fiz. Bir yerde t\u0131kan\u0131rsan, merak etme; deneme yan\u0131lma ile yo\u011frulmu\u015f k\u00fc\u00e7\u00fck hikayeler payla\u015faca\u011f\u0131m. Hani \u015fu tahtaya tebe\u015firle not etmi\u015f gibi hat\u0131rlatmalar olacak.<\/p>\n<p>Okurken akl\u0131nda bir senaryo canland\u0131r: \u00dcretim veritaban\u0131n ufak bir VPS\u2019te ko\u015fturuyor, trafik orta halli, ama veri \u00f6nemli. Bir kullan\u0131c\u0131 hatas\u0131, beklenmeyen bir sorgu, gereksiz bir \u201cDROP\u201d \u2013 her \u015fey olabilir. O y\u00fczden basit bir rutin kuruyoruz: <strong>Tam yedekleri<\/strong> d\u00fczenli al, <strong>WAL\u2019leri<\/strong> ak\u0131t, <strong>PITR<\/strong> ile geri d\u00f6nmeyi prova et. Haz\u0131rsan, \u00f6nce birka\u00e7 temel kavram\u0131 \u201cmutfa\u011fa girer gibi\u201d sakin sakin netle\u015ftirelim.<\/p>\n<h2 id='section-2'><span id=\"Neyi_Neden_Yaptigimizi_Bilerek_Baslayalim\">Neyi, Neden Yapt\u0131\u011f\u0131m\u0131z\u0131 Bilerek Ba\u015flayal\u0131m<\/span><\/h2>\n<p>Mesela \u015f\u00f6yle d\u00fc\u015f\u00fcn: Veritaban\u0131n\u0131 bir foto\u011fraf alb\u00fcm\u00fc gibi g\u00f6r. Tam yedek, o alb\u00fcm\u00fcn net bir kopyas\u0131. Ama arada \u00e7ekti\u011fin foto\u011fraflar\u0131 tek tek alb\u00fcme eklemek istersin. <strong>WAL (Write-Ahead Logging)<\/strong> tam bu. Veritaban\u0131nda yap\u0131lan her de\u011fi\u015fiklik \u00f6nce bu g\u00fcnl\u00fck dosyalar\u0131na yazar. Biz bu g\u00fcnl\u00fckleri saklarsak, tam yedekten ba\u015flay\u0131p \u201czamanda ileri sararak\u201d belirli bir saniyeye ula\u015fabiliriz. \u0130\u015fte <strong>PITR<\/strong> b\u00f6yle \u00e7al\u0131\u015f\u0131r.<\/p>\n<p><strong>pgBackRest<\/strong> ise i\u015fin a\u015f\u00e7\u0131ba\u015f\u0131s\u0131. Tam yedek al\u0131r, <strong>art\u0131ml\u0131<\/strong> yedekleri y\u00f6netir, <strong>WAL ar\u015fivleme<\/strong> i\u00e7in PostgreSQL ile el s\u0131k\u0131\u015f\u0131r, saklama politikalar\u0131n\u0131 uygular ve geri y\u00fcklerken rehberlik eder. Tek ba\u015f\u0131na PostgreSQL de yedeklenir, ama pgBackRest i\u015fi d\u00fczenli ve g\u00fcvenli hale getirir. Hata pay\u0131n\u0131 azalt\u0131r, ad\u0131mlar\u0131 kal\u0131ba sokar.<\/p>\n<p>VPS taraf\u0131nda da k\u00fc\u00e7\u00fck ama \u00f6nemli noktalar var. Disk I\/O yetenekleri, a\u011f gecikmesi, depolama alan\u0131, hatta saat dilimi. Hepsi sonunda PITR deneyimini etkiler. Mesela loglara bakarken bir saat kaymas\u0131, seni yanl\u0131\u015f hedef zamana s\u00fcr\u00fckleyebilir. Bu y\u00fczden \u201cne, nerede, neden\u201d sorular\u0131n\u0131 ba\u015ftan netle\u015ftirmek iyi bir al\u0131\u015fkanl\u0131k.<\/p>\n<h2 id='section-3'><span id=\"Ortami_Kuruyoruz_pgBackRest_PostgreSQL_ve_Yol_Haritasi\">Ortam\u0131 Kuruyoruz: pgBackRest, PostgreSQL ve Yol Haritas\u0131<\/span><\/h2>\n<h3><span id=\"Hangi_parcalara_ihtiyacimiz_var\">Hangi par\u00e7alara ihtiyac\u0131m\u0131z var?<\/span><\/h3>\n<p>Senaryomuz \u015f\u00f6yle: Ubuntu\/Debian tabanl\u0131 bir VPS, PostgreSQL 14 veya 15, yan\u0131nda pgBackRest. Depolamay\u0131 yerelde tutaca\u011f\u0131z; istersen sonra uzak bir sunucuya da replikasyon veya dosya senkronizasyonu ekleyebilirsin. Temel hedef, tek bir VPS\u2019te bile d\u00fczg\u00fcn yedek ak\u0131\u015f\u0131 kurmak.<\/p>\n<h3><span id=\"pgBackRest_kurulumu\">pgBackRest kurulumu<\/span><\/h3>\n<p>Da\u011f\u0131t\u0131ma g\u00f6re paket depolar\u0131nda pgBackRest mevcut. Yoksa kaynak koddan kurulum da olur ama paketler i\u015fimizi g\u00f6recektir. \u00d6rne\u011fin Debian\/Ubuntu taraf\u0131nda:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo apt update\nsudo apt install -y pgbackrest\n\n# PostgreSQL kimdir, nerededir? Tipik dizin \u00f6rnekleri:\n# \/var\/lib\/postgresql\/15\/main  (Debian\/Ubuntu)\n# pgdata de\u011fi\u015febilir, dikkat.\n<\/code><\/pre>\n<p>pgBackRest kendi yap\u0131land\u0131rma klas\u00f6r\u00fcn\u00fc kullan\u0131r. Varsay\u0131lan olarak <strong>\/etc\/pgbackrest<\/strong> ve repository i\u00e7in <strong>\/var\/lib\/pgbackrest<\/strong> iyidir. Dizin izinleri ve sahiplik \u00e7ok kritik. pgBackRest\u2019i <strong>postgres<\/strong> kullan\u0131c\u0131s\u0131 \u00e7al\u0131\u015ft\u0131rmal\u0131. Reponun sahibi de o olmal\u0131.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo mkdir -p \/etc\/pgbackrest\nsudo mkdir -p \/var\/lib\/pgbackrest\nsudo chown -R postgres:postgres \/etc\/pgbackrest \/var\/lib\/pgbackrest\nsudo chmod 750 \/var\/lib\/pgbackrest\n<\/code><\/pre>\n<p>\u015eimdi temel bir <strong>\/etc\/pgbackrest\/pgbackrest.conf<\/strong> yazal\u0131m. Basit ba\u015flayal\u0131m; sonra zenginle\u015ftiririz.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo -u postgres bash -c 'cat &gt; \/etc\/pgbackrest\/pgbackrest.conf &lt;&lt;&quot;EOF&quot;\n[global]\nrepo1-path=\/var\/lib\/pgbackrest\nrepo1-retention-full=4\nrepo1-retention-diff=14\nrepo1-cipher-type=aes-256-cbc\nrepo1-cipher-pass=GUVENLI_BIR_SIFRE\ncompress-type=zst\nstart-fast=y\n\n[main]\npg1-path=\/var\/lib\/postgresql\/15\/main\nEOF'\n<\/code><\/pre>\n<p>Burada saklama politikalar\u0131n\u0131 kabaca \u00e7izdik. Tam yedeklerden d\u00f6rt kopya, diferansiyel yedeklerden iki haftal\u0131k bir ge\u00e7mi\u015f gibi d\u00fc\u015f\u00fcnebilirsin. Parola \u00fcretmek i\u00e7in basit bir \u015fifre t\u00fcretme scripti kullanabilirsin. \u015eifreyi saklarken de gizli dosyalarda tutmay\u0131 unutma. Evde anahtar\u0131n\u0131 mat\u0131n alt\u0131na koymazs\u0131n, burada da koyma.<\/p>\n<h3><span id=\"PostgreSQLi_WAL_arsivlemeye_hazirlamak\">PostgreSQL\u2019i WAL ar\u015fivlemeye haz\u0131rlamak<\/span><\/h3>\n<p>\u015eimdi veritaban\u0131na d\u00f6nelim. <strong>wal_level<\/strong> en az\u0131ndan \u201creplica\u201d, <strong>archive_mode<\/strong> a\u00e7\u0131k olacak. <strong>archive_command<\/strong> ise pgBackRest\u2019in <strong>archive-push<\/strong> komutunu \u00e7a\u011f\u0131racak. postgresql.conf\u2019u d\u00fczenleyelim.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># \/etc\/postgresql\/15\/main\/postgresql.conf\nwal_level = replica\narchive_mode = on\narchive_command = 'pgbackrest --stanza=main archive-push %p'\nmax_wal_senders = 3\n<\/code><\/pre>\n<p>Ard\u0131ndan PostgreSQL\u2019i yeniden y\u00fckle:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo systemctl reload postgresql\n<\/code><\/pre>\n<p>pgBackRest\u2019e bu k\u00fcmenin bir ad\u0131 oldu\u011funa dair \u201cstanza\u201d tan\u0131taca\u011f\u0131z. Bu, birden fazla veritaban\u0131n\u0131 takip etmek istedi\u011finde hayat kurtar\u0131r. Tek veritaban\u0131m\u0131z var ama yine de iyi bir al\u0131\u015fkanl\u0131k.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo -u postgres pgbackrest --stanza=main stanza-create\nsudo -u postgres pgbackrest --stanza=main check\n<\/code><\/pre>\n<p>\u201ccheck\u201d \u00e7\u0131kt\u0131s\u0131nda ar\u015fiv komutu, repo eri\u015fimi ve dizin izinleriyle ilgili uyar\u0131lar almamal\u0131s\u0131n. Bir uyar\u0131 gelirse genellikle sahiplik veya yol hatas\u0131d\u0131r. Sakin ol, tekrar kontrol et.<\/p>\n<h2 id='section-4'><span id=\"Ilk_Yedek_Tam_Sonra_Diferansiyel_WALler_Aksin\">\u0130lk Yedek: Tam, Sonra Diferansiyel; WAL\u2019ler Aks\u0131n<\/span><\/h2>\n<p>\u0130lk tam yede\u011fi alal\u0131m. Bu, alb\u00fcm\u00fcn eksiksiz kopyas\u0131. Sonras\u0131nda diferansiyel ve art\u0131ml\u0131 yedeklerle yaln\u0131zca de\u011fi\u015fen sayfalar\u0131 ekleriz.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo -u postgres pgbackrest --stanza=main --type=full backup\nsudo -u postgres pgbackrest info\n<\/code><\/pre>\n<p>\u201cinfo\u201d \u00e7\u0131kt\u0131s\u0131 \u00e7ok \u015feyi s\u00f6yler: ka\u00e7 yede\u011fin var, hangi tarihte al\u0131nm\u0131\u015f, toplam boyutlar, WAL ar\u015fivleme durumu. Bu komutla d\u00fczenli olarak yoklama yapmak, \u201cher \u015fey yolunda m\u0131?\u201d sorusuna \u00e7abuk cevap verir.<\/p>\n<p>Yedekleri rutin hale getirmek i\u00e7in bir zamanlay\u0131c\u0131 ekle. Cron olabilir, ama ben <strong>systemd timer<\/strong> kullanmay\u0131 seviyorum. Hem loglar d\u00fczenli, hem de servis mant\u0131\u011f\u0131na oturuyor.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># \/etc\/systemd\/system\/pgbackrest-full.timer\n[Unit]\nDescription=pgBackRest Full Backup Timer\n\n[Timer]\nOnCalendar=Sun 03:00\nPersistent=true\n\n[Install]\nWantedBy=timers.target\n\n# \/etc\/systemd\/system\/pgbackrest-full.service\n[Unit]\nDescription=pgBackRest Full Backup\n\n[Service]\nType=oneshot\nUser=postgres\nExecStart=\/usr\/bin\/pgbackrest --stanza=main --type=full backup\n\n# Diferansiyel i\u00e7in benzer bir \u00e7ift ekleyebilirsin:\n# \/etc\/systemd\/system\/pgbackrest-diff.timer (OnCalendar=Mon..Sat 03:00)\n# \/etc\/systemd\/system\/pgbackrest-diff.service (ExecStart=... --type=diff)\n<\/code><\/pre>\n<p>Timer\u2019lar\u0131 etkinle\u015ftir:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo systemctl daemon-reload\nsudo systemctl enable --now pgbackrest-full.timer\n# Diff i\u00e7in de benzer \u015fekilde enable\/now\n<\/code><\/pre>\n<p>Art\u0131k resim netle\u015fiyor: Pazar sabahlar\u0131 tam yedek, hafta i\u00e7i diferansiyeller. WAL ar\u015fivleme ise s\u00fcrekli ak\u0131yor. Yani veritaban\u0131ndaki de\u011fi\u015fiklikler \u201canbean\u201d repo\u2019ya ta\u015f\u0131n\u0131yor. Bu ak\u0131\u015f, PITR\u2019nin yak\u0131t\u0131.<\/p>\n<h2 id='section-5'><span id=\"PITR_Zamani_Geri_Sarmak_Nasil_Hissettirir\">PITR: Zaman\u0131 Geri Sarmak Nas\u0131l Hissettirir?<\/span><\/h2>\n<p>Gelelim i\u015fin en tatl\u0131 k\u0131sm\u0131na. Diyelim ki saat 10:00\u2019da yanl\u0131\u015f bir g\u00fcncelleme \u00e7al\u0131\u015ft\u0131rd\u0131n, orada dengesiz bir veri olu\u015ftu. Sen asl\u0131nda 09:52\u2019ye geri d\u00f6nmek istiyorsun. O halde \u00f6nce bir nefes al, sonra \u015fu ad\u0131mlar\u0131 takip et.<\/p>\n<h3><span id=\"Hedef_zamani_belirlemek\">Hedef zaman\u0131 belirlemek<\/span><\/h3>\n<p>Uygulama loglar\u0131ndan, PostgreSQL loglar\u0131ndan veya olay hat\u0131randan hedef zaman\u0131 netle\u015ftir. Saniye seviyesinde kabaca bir hedef se\u00e7. \u201cBiraz \u00f6ncesi de olur\u201d dersen, birka\u00e7 saniye \u00f6nceyi kullan. Timezone\u2019u unutma; sunucu UTC ise, yerel saatine g\u00f6re \u00e7evirmelisin.<\/p>\n<h3><span id=\"Veritabanini_durdurmak\">Veritaban\u0131n\u0131 durdurmak<\/span><\/h3>\n<p>Restorasyon \u00f6ncesi PostgreSQL\u2019i kapat\u0131r\u0131z. Veri dizinini bo\u015faltmak veya kenara almak gerekir. pgBackRest, restore s\u0131ras\u0131nda dizini doldurur.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo systemctl stop postgresql\nsudo mv \/var\/lib\/postgresql\/15\/main \/var\/lib\/postgresql\/15\/main.bak.$(date +%s)\nsudo -u postgres mkdir -p \/var\/lib\/postgresql\/15\/main\n<\/code><\/pre>\n<h3><span id=\"pgBackRest_restore_komutu\">pgBackRest restore komutu<\/span><\/h3>\n<p>Art\u0131k geri y\u00fcklemeyi, hedef zamana g\u00f6re tetikliyoruz. pgBackRest, PostgreSQL 12+ s\u00fcr\u00fcmlerinde gereken <strong>recovery.signal<\/strong> ve restore ayarlar\u0131n\u0131 otomatik yazar. Hedef zaman\u0131 ve davran\u0131\u015f\u0131 net s\u00f6ylersin, o da gereken WAL\u2019leri s\u0131rayla uygular.<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo -u postgres pgbackrest \n  --stanza=main \n  --type=time \n  --target='2025-11-11 09:52:00' \n  --target-action=promote \n  --delta \n  restore\n<\/code><\/pre>\n<p>Burada \u201cdelta\u201d, var olan dosyalar\u0131 tekrar indirmemek i\u00e7in ak\u0131ll\u0131 bir k\u0131sayol. Ama ilk denemelerde temiz dizinle \u00e7al\u0131\u015fmak daha anla\u015f\u0131l\u0131r olabilir. Restore bitince PostgreSQL\u2019i ba\u015flat:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo systemctl start postgresql\n<\/code><\/pre>\n<p>Loglar\u0131 kontrol et. Genelde \u201crecovery\u201d tamamland\u0131, \u201cpromote\u201d edildi gibi net mesajlar g\u00f6r\u00fcrs\u00fcn. Hedef saniyeye gelince sistem aya\u011fa kalkar. \u015eimdi kritik an: Uygulamada k\u0131sa bir sa\u011fl\u0131k kontrol\u00fc yap. O yanl\u0131\u015f g\u00fcncellemenin etkileri kaybolmu\u015f mu, bekledi\u011fin veri g\u00f6r\u00fcn\u00fcr m\u00fc?<\/p>\n<p>Burada bir parantez: Daha kapsaml\u0131 ak\u0131\u015f ve sinyal dosyalar\u0131 i\u00e7in <a href=\"https:\/\/www.postgresql.org\/docs\/current\/backup-recovery.html\" rel=\"nofollow noopener\" target=\"_blank\">PostgreSQL yedekleme ve kurtarma ak\u0131\u015f\u0131n\u0131<\/a> incelemek iyi gelir. Ayr\u0131ca pgBackRest\u2019in ayr\u0131nt\u0131l\u0131 se\u00e7enekleri de \u00e7ok zengin; merak ettik\u00e7e <a href=\"https:\/\/pgbackrest.org\/user-guide.html\" rel=\"nofollow noopener\" target=\"_blank\">pgBackRest kullan\u0131c\u0131 rehberini<\/a> elinin alt\u0131nda tut.<\/p>\n<h2 id='section-6'><span id=\"Kucuk_Ince_Ayarlar_Tutma_Politikasi_Sikistirma_Sifreleme\">K\u00fc\u00e7\u00fck \u0130nce Ayarlar: Tutma Politikas\u0131, S\u0131k\u0131\u015ft\u0131rma, \u015eifreleme<\/span><\/h2>\n<p>Yedeklemek kadar silmek de sorumluluk ister. Depolama alan\u0131 s\u0131n\u0131rl\u0131ysa, <strong>retention<\/strong> de\u011ferlerini ger\u00e7ek\u00e7i belirle. Tam yedek say\u0131s\u0131 az olursa geri d\u00f6n\u00fc\u015f yollar\u0131n daral\u0131r; \u00e7ok olursa disk dolar. \u0130yi bir ba\u015flang\u0131\u00e7, ayl\u0131k d\u00f6rt tam yedek ve aralarda iki haftal\u0131k diferansiyeller. Bu, hem alan\u0131 hem de geri d\u00f6n\u00fc\u015f esnekli\u011fini dengeler.<\/p>\n<p>S\u0131k\u0131\u015ft\u0131rmada <strong>zstd<\/strong> gayet seri ve verimli. CPU b\u00fct\u00e7eni zorlamadan sa\u011flam kazan\u00e7 sa\u011flar. \u015eifreleme i\u00e7in AES-256 iyi bir tercih. Ama anahtar y\u00f6netimini ciddiye al. Yedek anahtar\u0131n\u0131 farkl\u0131 bir yerde, ayr\u0131 bir kasada tutmak gibi d\u00fc\u015f\u00fcn. As\u0131l sunucuda tuttu\u011fun \u015fifre, ba\u015fka bir yedekleme notunda tekrar edilmeli ama herkese a\u00e7\u0131k olmamal\u0131.<\/p>\n<p>\u0130\u015fin bir de <strong>repo g\u00fcvenli\u011fi<\/strong> k\u0131sm\u0131 var. O dizine herkesin yazabilmesi olmaz. Sahiplik <strong>postgres<\/strong>, mod 750 veya 700 olsun. Yedeklerin b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc bozacak en k\u00fc\u00e7\u00fck izinsiz de\u011fi\u015fiklikte restorasyon s\u00fcreci maskara olur. O y\u00fczden izinler konusuna \u201ck\u0131r\u0131lacak e\u015fya\u201d hassasiyetiyle yakla\u015f.<\/p>\n<h2 id='section-7'><span id=\"Yedekleri_Duzenli_Test_Etmek_Runbook_Alarm_Kucuk_Provalar\">Yedekleri D\u00fczenli Test Etmek: Runbook, Alarm, K\u00fc\u00e7\u00fck Provalar<\/span><\/h2>\n<p>Bir g\u00fcn ger\u00e7ekten PITR yapmak zorunda kal\u0131rsan, o an \u201cilk kez\u201d yapmak istemezsin. Bu y\u00fczden k\u00fc\u00e7\u00fck bir test plan\u0131 \u015fart. Ben genelde \u015f\u00f6yle yapar\u0131m: Ayda bir staging bir VPS\u2019te orijinal sunucunun yede\u011fini indirir, <strong>restore<\/strong> dener, uygulamay\u0131 smoketest ile yoklar\u0131m. Rutin olunca, \u00fcretimde hata oldu\u011funda elin hi\u00e7 titremez.<\/p>\n<p>pgBackRest\u2019in bilgi komutlar\u0131 g\u00fcnl\u00fck hayatta \u00e7ok pratik. \u201cinfo\u201d ile durum al, \u201ccheck\u201d ile tutarl\u0131l\u0131k yokla. WAL ar\u015fivlemenin akt\u0131\u011f\u0131n\u0131 teyit etmek i\u00e7in ar\u015fiv klas\u00f6r\u00fcnden dosya ak\u0131\u015f\u0131na ara ara bak. PostgreSQL taraf\u0131nda \u201carchive\u201d ile ilgili log sat\u0131rlar\u0131 temiz mi, tekrar eden hata var m\u0131?<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo -u postgres pgbackrest info\nsudo -u postgres pgbackrest --stanza=main check\n<\/code><\/pre>\n<p>Yine benzer bir konuda veritaban\u0131 sa\u011fl\u0131\u011f\u0131n\u0131 uzun vadede korumak i\u00e7in <a href=\"https:\/\/www.dchost.com\/blog\/postgresql-autovacuum-tuning-ve-bloatla-barismak-vpste-pratik-ayarlar-ve-pg_repack-ile-neredeyse-sifir-kesinti\/\">Autovacuum ayarlar\u0131n\u0131 tatl\u0131 tatl\u0131 d\u00fczenlemek ve bloat\u2019la bar\u0131\u015fmak<\/a> da iyi bir al\u0131\u015fkanl\u0131k. Yedekleme ne kadar m\u00fckemmel olursa olsun, \u015fi\u015fmi\u015f tablolar ya da ihmal edilmi\u015f vakum i\u015fleri restorasyonu da a\u011f\u0131rla\u015ft\u0131r\u0131r.<\/p>\n<h2 id='section-8'><span id=\"Gercek_Hayattan_Kucuk_Dersler_Izinler_Saat_Dilimi_WAL_Taskini\">Ger\u00e7ek Hayattan K\u00fc\u00e7\u00fck Dersler: \u0130zinler, Saat Dilimi, WAL Ta\u015fk\u0131n\u0131<\/span><\/h2>\n<p>\u0130\u015fin mutfa\u011f\u0131nda s\u0131k tak\u0131lan birka\u00e7 ta\u015f var. Birincisi <strong>izinler<\/strong>. pgBackRest repo\u2019su ve \/etc\/pgbackrest alt\u0131nda yanl\u0131\u015f sahiplik veya fazla a\u00e7\u0131k izinler olursa, bazen kibar uyar\u0131lar, bazen de sert hatalar al\u0131rs\u0131n. \u0130kincisi <strong>saat dilimi<\/strong>. PITR hedefini yazarken UTC mi, yerel saat mi, net ol. \u00dc\u00e7\u00fcnc\u00fcs\u00fc <strong>WAL ta\u015fk\u0131n\u0131<\/strong>. Anl\u0131k \u00e7ok yo\u011fun yazma oldu\u011funda repo\u2019ya akan WAL say\u0131s\u0131 artar. Bu normaldir; disk alan\u0131n\u0131 ve a\u011f\u0131n\u0131 buna g\u00f6re planla.<\/p>\n<p>Bir kere de \u015funu ya\u015fam\u0131\u015ft\u0131m: \u201carchive_command\u201d g\u00fczelce yaz\u0131lm\u0131\u015f ama sonuna noktal\u0131 virg\u00fcl koymay\u0131 unutmu\u015fum. postgresql.conf\u2019da basit bir yaz\u0131m hatas\u0131 bile ar\u015fivlemeyi sessizce bozabilir. Bir reload sonras\u0131 loglar\u0131 g\u00f6z ucuyla kontrol etmek bu y\u00fczden kritik.<\/p>\n<p>Bir de s\u00fcr\u00fcm ayr\u0131nt\u0131s\u0131 var: PostgreSQL 12\u2019den itibaren <strong>recovery.conf<\/strong> kalkt\u0131, <strong>recovery.signal<\/strong> ve <strong>standby.signal<\/strong> gibi sinyal dosyalar\u0131 geldi. pgBackRest bu ayr\u0131nt\u0131lar\u0131 senin yerine hallediyor ama akl\u0131nda bulunsun. Merak edersen <a href=\"https:\/\/www.postgresql.org\/docs\/current\/continuous-archiving.html\" rel=\"nofollow noopener\" target=\"_blank\">s\u00fcrekli ar\u015fivleme ve PITR rehberine<\/a> g\u00f6z atabilirsin.<\/p>\n<h2 id='section-9'><span id=\"Yapilandirmayi_Zenginlestirmek_Uzak_Repo_Ayri_Disk_Sistem_Servisleri\">Yap\u0131land\u0131rmay\u0131 Zenginle\u015ftirmek: Uzak Repo, Ayr\u0131 Disk, Sistem Servisleri<\/span><\/h2>\n<p>\u0130\u015fler ciddile\u015fince yedekleri uzak bir sunucuya aktarmak istersin. pgBackRest bu konuda esnek; SSH \u00fczerinden <strong>repo-host<\/strong> tan\u0131m\u0131yla uzak depoyu y\u00f6netebilirsin. A\u011f gecikmesi artar ama felaket senaryosunda veriyi ba\u015fka bir yerde tutman\u0131n g\u00fcveni paha bi\u00e7ilmez. Yerel disk de ayr\u0131ca \u00f6nemli; ayn\u0131 VPS\u2019te bile olsa yedekleri ayr\u0131 bir diske koymak riski azalt\u0131r.<\/p>\n<p>Systemd taraf\u0131nda k\u00fc\u00e7\u00fck incelikler var. Servislere \u201cStopWhenUnneeded\u201d gibi parametrelerle k\u0131sa \u00f6m\u00fcrl\u00fc i\u015fler tan\u0131mlars\u0131n. Timer\u2019lar ba\u015far\u0131s\u0131z olursa journalctl ile \u00e7\u0131kt\u0131y\u0131 al, hatay\u0131 birlikte \u00e7\u00f6zen arkada\u015flar gibi sevgiyle yakla\u015f\u0131rs\u0131n. Kurtarma an\u0131nda bir <strong>runbook<\/strong> elinin alt\u0131nda olsun: \u201c\u00d6nce durdur, yedek dizini ta\u015f\u0131r, restore, ba\u015flat, kontrol listesi.\u201d Tek sayfal\u0131k bir not bile zor anlarda alt\u0131n de\u011ferinde.<\/p>\n<p>Bu a\u015famada \u201cizleme\u201dyi de d\u00fc\u015f\u00fcn. Yedek boyutlar\u0131, son yedek zaman\u0131, WAL ak\u0131\u015f\u0131, ba\u015far\u0131s\u0131z yedek denemeleri. Ufak bir panel, bir iki alarm kural\u0131 ekleyince geceleri daha rahat uyursun. pgBackRest, komutlarla okunabilir bir \u00f6zet verdi\u011fi i\u00e7in basit bash script\u2019leriyle bile uyar\u0131lar kurulur.<\/p>\n<h2 id='section-10'><span id=\"Adim_Adim_Ozet_Akis_Kur_Dogrula_Yedekle_Test_Et\">Ad\u0131m Ad\u0131m \u00d6zet Ak\u0131\u015f: Kur, Do\u011frula, Yedekle, Test Et<\/span><\/h2>\n<p>\u015eimdiye kadar anlatt\u0131klar\u0131m\u0131z\u0131 k\u00fc\u00e7\u00fck bir ak\u0131\u015f halinde kafanda netle\u015ftir: \u00d6nce pgBackRest\u2019i kurdun ve repo ile konfig\u00fcrasyonu haz\u0131rlad\u0131n. PostgreSQL taraf\u0131nda archive_mode\u2019u a\u00e7t\u0131n, archive_command\u2019\u0131 pgBackRest\u2019e ba\u011flad\u0131n. Stanza\u2019y\u0131 yaratt\u0131n, check ile do\u011frulad\u0131n. \u0130lk tam yede\u011fi ald\u0131n. Timer\u2019larla d\u00fczen kurdun. Sonra bir g\u00fcn, bir \u015feyler ters gitti. Panik yok. PostgreSQL\u2019i durdurdun, data dizinini kenara ald\u0131n, restore\u2019u hedef zamana g\u00f6re \u00e7al\u0131\u015ft\u0131rd\u0131n, servis ba\u015flad\u0131 ve g\u00fclerek \u00e7ay\u0131n\u0131 yudumlad\u0131n.<\/p>\n<p>Uzun gibi g\u00f6r\u00fcnse de birka\u00e7 kez yapt\u0131ktan sonra elin al\u0131\u015f\u0131yor. Hele bir iki test restore yapt\u0131ysan, ger\u00e7ek bir geri d\u00f6n\u00fc\u015f an\u0131nda elin kaym\u0131yor. \u015eu da ger\u00e7ek: Yedek almak, sadece komut \u00e7al\u0131\u015ft\u0131rmak de\u011fil. <strong>Test etmek<\/strong>, <strong>saklama politikas\u0131n\u0131<\/strong> do\u011fru ayarlamak, <strong>izlemek<\/strong> ve <strong>belgelemek<\/strong> de bu i\u015fin bir par\u00e7as\u0131.<\/p>\n<p>Buraya kadar teknik anlat\u0131mda ayr\u0131nt\u0131ya girdik ama hi\u00e7biri g\u00f6z\u00fcn\u00fc korkutmas\u0131n. Ad\u0131mlar\u0131n her biri anlaml\u0131 ve sonucunu an\u0131nda g\u00f6r\u00fcyorsun. Birka\u00e7 k\u00fc\u00e7\u00fck prova ile senin i\u00e7in s\u0131radan bir rutine d\u00f6n\u00fc\u015fecek.<\/p>\n<h2 id='section-11'><span id=\"Sik_Karsilastigim_Sorular_ve_Kucuk_Notlar\">S\u0131k Kar\u015f\u0131la\u015ft\u0131\u011f\u0131m Sorular ve K\u00fc\u00e7\u00fck Notlar<\/span><\/h2>\n<p>\u201cPeki, tamam da en s\u0131k neler ters gidiyor?\u201d dersen, akl\u0131ma ilk gelenler: wrong owner\/permissions, archive_command yaz\u0131m hatalar\u0131, yetersiz disk, hedef zaman\u0131n yanl\u0131\u015f time zone ile hesaplanmas\u0131, repo \u015fifresinin unutulmas\u0131. Bunlar\u0131n hepsi, k\u00fc\u00e7\u00fck bir kontrol listesiyle \u00f6nlenebilir. Hatta restorasyon sonras\u0131 uygulama cache\u2019lerini temizlemeyi bile not d\u00fc\u015fmek iyi fikir. Geri d\u00f6n\u00fc\u015f tamamlan\u0131yor ama uygulama katman\u0131 eski cache\u2019i g\u00f6sterince \u201chata var\u201d san\u0131yorlar. Sorun bir de\u011fil, iki katmanda olabiliyor.<\/p>\n<p>Konfig\u00fcrasyon dosyalar\u0131n\u0131 de\u011fi\u015ftirirken kopyas\u0131n\u0131 al. \u00d6zellikle postgresql.conf ve pgbackrest.conf. Bir \u015feyleri bozarsan geri d\u00f6n\u00fc\u015f \u00e7ok rahatlar. K\u00fc\u00e7\u00fck dokunu\u015flar, b\u00fcy\u00fck rahatlamalar.<\/p>\n<p>Ve son bir parola notu: repo \u015fifresini yaln\u0131zca konfig\u00fcrasyonda b\u0131rakma. G\u00fcvenli bir parola kasas\u0131nda, ba\u015fka bir yerde, hatta yazd\u0131r\u0131lm\u0131\u015f ama kilitli bir \u00e7ekmecede bile tutabilirsin. En k\u00f6t\u00fc g\u00fcn geldi\u011finde tek bir d\u00fc\u011f\u00fcme ba\u011fl\u0131 kalmak istemezsin.<\/p>\n<h2 id='section-12'><span id=\"Kapanis_Bugun_Kucuk_Bir_Adim_Yarin_Buyuk_Bir_Rahatlik\">Kapan\u0131\u015f: Bug\u00fcn K\u00fc\u00e7\u00fck Bir Ad\u0131m, Yar\u0131n B\u00fcy\u00fck Bir Rahatl\u0131k<\/span><\/h2>\n<p>Bazen birka\u00e7 komut, birka\u00e7 iyi al\u0131\u015fkanl\u0131k ve bir tutam sab\u0131r, i\u015fini bamba\u015fka bir seviyeye ta\u015f\u0131r. <strong>pgBackRest ile WAL ar\u015fivleme<\/strong> ve <strong>PITR<\/strong> tam da b\u00f6yle. \u0130lk bak\u0131\u015fta karma\u015f\u0131k g\u00f6r\u00fcnebilir ama bir kere ad\u0131mlar\u0131 izleyince gerisi \u00e7orap s\u00f6k\u00fc\u011f\u00fc gibi geliyor. \u00dcstelik bu yakla\u015f\u0131m, sadece veri kurtarmak i\u00e7in de\u011fil, g\u00f6n\u00fcl rahatl\u0131\u011f\u0131yla uyumak i\u00e7in de g\u00fczel bir yat\u0131r\u0131m.<\/p>\n<p>Sana son birka\u00e7 pratik tavsiye b\u0131rakay\u0131m: \u00d6nce k\u00fc\u00e7\u00fck bir veritaban\u0131nda deneme yap. Bir tablo olu\u015ftur, birka\u00e7 sat\u0131r ekle, yanl\u0131\u015f bir g\u00fcncelleme yap ve PITR ile geri d\u00f6n. Sonra bunu yaz; bir \u201crunbook\u201d olarak ekip arkada\u015flar\u0131nla payla\u015f. Zamanlay\u0131c\u0131lar\u0131 ekle, loglara \u015f\u00f6yle bir g\u00f6z atmay\u0131 al\u0131\u015fkanl\u0131k haline getir. \u0130ki ayda bir de tam restorasyon provas\u0131 yap ki, reflekslerin diri kals\u0131n.<\/p>\n<p>\u0130stersen t\u00fcm detaylar\u0131 daha da derinle\u015ftirmek i\u00e7in <a href=\"https:\/\/pgbackrest.org\/user-guide.html\" rel=\"nofollow noopener\" target=\"_blank\">pgBackRest\u2019in kullan\u0131c\u0131 rehberine<\/a> g\u00f6z atabilir, PostgreSQL\u2019in <a href=\"https:\/\/www.postgresql.org\/docs\/current\/continuous-archiving.html\" rel=\"nofollow noopener\" target=\"_blank\">s\u00fcrekli ar\u015fivleme ve PITR<\/a> konular\u0131n\u0131 sindire sindire okuyabilirsin. Umar\u0131m bu yaz\u0131 sana yol g\u00f6sterir. Tak\u0131ld\u0131\u011f\u0131n bir ad\u0131m olursa, en k\u00f6t\u00fc ihtimalle bir mola verip geri d\u00f6n; bazen \u00e7\u00f6z\u00fcm o arada kendini g\u00f6steriyor. Bir dahaki yaz\u0131da g\u00f6r\u00fc\u015fmek \u00fczere; verilerini sev, yedeklerini daha \u00e7ok sev.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>\u0130&ccedil;indekiler1 Hi\u00e7 \u201cKe\u015fke Zaman\u0131 Geri Alsam\u201d Dedi\u011fin Oldu mu?2 Neyi, Neden Yapt\u0131\u011f\u0131m\u0131z\u0131 Bilerek Ba\u015flayal\u0131m3 Ortam\u0131 Kuruyoruz: pgBackRest, PostgreSQL ve Yol Haritas\u01313.1 Hangi par\u00e7alara ihtiyac\u0131m\u0131z var?3.2 pgBackRest kurulumu3.3 PostgreSQL\u2019i WAL ar\u015fivlemeye haz\u0131rlamak4 \u0130lk Yedek: Tam, Sonra Diferansiyel; WAL\u2019ler Aks\u0131n5 PITR: Zaman\u0131 Geri Sarmak Nas\u0131l Hissettirir?5.1 Hedef zaman\u0131 belirlemek5.2 Veritaban\u0131n\u0131 durdurmak5.3 pgBackRest restore komutu6 K\u00fc\u00e7\u00fck \u0130nce Ayarlar: [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1681,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-1680","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts\/1680","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/comments?post=1680"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/posts\/1680\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/media\/1681"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/media?parent=1680"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/categories?post=1680"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/wp-json\/wp\/v2\/tags?post=1680"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}