Mengopi folder data PostgreSQL dengan cp saat server sedang berjalan menghasilkan salinan yang rusak: halaman data berubah di tengah penyalinan, dan WAL yang dibutuhkan untuk menyatukan perubahan itu mungkin tidak ikut tersalin. PostgreSQL menyediakan satu alat resmi yang mengatasi masalah tersebut: pg_basebackup. Alat ini mengambil salinan menyeluruh satu cluster — semua database, role, dan konfigurasi di dalamnya — dalam keadaan konsisten lewat API backup internal server. Hasilnya disebut base backup, yaitu fondasi tempat pemulihan fisik dan point-in-time recovery dibangun. Chapter ini membedah cara kerja pg_basebackup, pilihan format plain versus tar, tiga strategi penanganan WAL, sampai verifikasi hasil backup memakai backup_manifest — melanjutkan konsep backup fisik dari chapter Physical Backup .

Base Backup Menyeluruh dari Cluster #

pg_basebackup terhubung ke server lewat protokol replikasi, bukan lewat SQL biasa. Setelah tersambung, server menandai titik mulai backup di WAL, mengirim seluruh isi data directory dalam keadaan konsisten, lalu menandai titik selesai. Dua penanda itu ditulis ke file backup_label di dalam hasil backup, sehingga saat salinan ini dinyalakan ulang, server tahu dari titik WAL mana replay harus dimulai. Karena yang disalin adalah data directory, hasilnya mencakup seluruh cluster: semua database sekaligus, bukan satu database seperti pada pg_dump.

Sejak PostgreSQL 13, setiap base backup juga disertai backup_manifest: daftar seluruh file beserta checksum masing-masing. Manifest inilah yang membuat integritas backup bisa diverifikasi secara independen — dibahas di bagian akhir chapter ini.

Prasyarat di Sisi Server #

Dua parameter menentukan apakah koneksi protokol replikasi akan diterima. Query berikut membacanya dari server latihan:

sql prasyarat.sql
-- pg_basebackup bekerja lewat protokol replikasi, bukan SQL biasa.
-- Tiga parameter ini menentukan apakah base backup bisa berjalan.
SHOW wal_level;

SHOW max_wal_senders;

SHOW wal_segment_size;

Output yang Dihasilkan:

text
 wal_level 
-----------
 replica
(1 row)

 max_wal_senders 
-----------------
 10
(1 row)

 wal_segment_size 
------------------
 16MB
(1 row)

Mari kita bedah tiga nilai itu:

  1. wal_level = replica: level penulisan WAL cukup untuk pengiriman data replikasi — syarat minimum pg_basebackup. Level minimal akan menolak koneksi backup.
  2. max_wal_senders = 10: server mengizinkan maksimal sepuluh proses pengirim WAL secara bersamaan; satu slot dipakai oleh setiap pg_basebackup yang berjalan, sisanya dipakai standby streaming.
  3. wal_segment_size = 16MB: ukuran satu segmen WAL bawaan — angka ini berperan saat kita memilih strategi penanganan WAL di bagian berikutnya.

Selain parameter, koneksi replikasi juga harus diizinkan pg_hba.conf melalui baris replication. Instalasi bawaan Debian dan PostgreSQL umumnya sudah menyediakannya untuk koneksi lokal — server latihan kita termasuk yang demikian, itulah mengapa contoh-contoh berikut berjalan tanpa penyetelan tambahan.

Format plain: Salinan Data Directory #

Opsi -Fp (format plain) menghasilkan struktur direktori yang persis mencerminkan data directory asli. Skrip berikut mengambil base backup lengkap ke /tmp/pgtutor-bb/plain, memeriksa strukturnya, lalu membersihkan hasilnya:

bash backup-plain.sh
#!/usr/bin/env bash
# Base backup format plain dengan WAL yang di-stream sekaligus.
set -euo pipefail

TUJUAN=/tmp/pgtutor-bb/plain

# Selalu mulai dari direktori kosong: pg_basebackup menolak direktori berisi.
rm -rf "$TUJUAN"

# -Fp  : format plain, struktur data directory disalin apa adanya
# -Xs  : WAL yang dibutuhkan backup ikut di-stream, backup jadi mandiri
# --checkpoint=fast : checkpoint dijalankan segera supaya backup cepat dimulai
pg_basebackup -D "$TUJUAN" -Fp -Xs --checkpoint=fast --no-password

# Struktur level atas hasil backup harus mencerminkan data directory.
ls -1 "$TUJUAN"

# backup_label menandai backup sah dan mencatat posisi WAL awal.
if [ -f "$TUJUAN/backup_label" ]; then
    echo "backup_label: ADA"
fi

# Versi mayor server yang dibackup.
cat "$TUJUAN/PG_VERSION"

# Selesai: hapus artefak lab.
rm -rf "$TUJUAN"

Output yang Dihasilkan:

text
PG_VERSION
backup_label
backup_manifest
base
global
pg_commit_ts
pg_dynshmem
pg_hba.conf
pg_ident.conf
pg_logical
pg_multixact
pg_notify
pg_replslot
pg_serial
pg_snapshots
pg_stat
pg_stat_tmp
pg_subtrans
pg_tblspc
pg_twophase
pg_wal
pg_xact
postgresql.auto.conf
postgresql.conf
backup_label: ADA
17

Kita bedah baris-baris penting skrip itu:

  1. Baris pg_basebackup -D "$TUJUAN" -Fp -Xs ...: -D menentukan direktori tujuan (dibuat otomatis bila belum ada), -Fp memilih format plain, dan --no-password mencegah prompt interaktif agar skrip aman dijalankan otomatis. Koneksi memakai variabel lingkungan PGHOST, PGPORT, dan PGUSER — pola yang sama dengan psql.
  2. Baris ls -1 "$TUJUAN": daftar entri level atas hasil backup. Nama seperti base, global, pg_wal, dan postgresql.conf adalah anatomi data directory yang dikenalkan di chapter Physical Backup — semuanya kini ada di salinan kita, lengkap dengan backup_label dan backup_manifest.
  3. Baris if [ -f "$TUJUAN/backup_label" ]: keberadaan backup_label adalah penanda paling cepat bahwa salinan berasal dari backup yang sah, bukan dari cp manual.
  4. Baris cat "$TUJUAN/PG_VERSION": file ini memuat versi mayor server (17) — angka yang menentukan biner server mana yang boleh menjalankan salinan ini.

Format tar dengan Kompresi #

Format kedua, -Ft, membungkus hasil backup menjadi file arsip tar. Ditambah opsi -z, tiap arsip dikompresi dengan gzip. Skrip berikut membandingkan bentuk hasilnya dengan format plain:

bash backup-tar.sh
#!/usr/bin/env bash
# Base backup format tar dengan kompresi gzip.
set -euo pipefail

TUJUAN=/tmp/pgtutor-bb/tar

rm -rf "$TUJUAN"

# -Ft : format tar, hasil berupa file arsip
# -z  : kompresi gzip untuk setiap arsip
# -Xs : WAL dikemas sebagai arsip terpisah pg_wal.tar.gz
pg_basebackup -D "$TUJUAN" -Ft -z -Xs --checkpoint=fast --no-password

# Format tar selalu menghasilkan kombinasi file ini.
ls -1 "$TUJUAN"

# Pastikan ketiga arsip benar-benar berisi (ukuran lebih dari nol).
for berkas in backup_manifest base.tar.gz pg_wal.tar.gz; do
    if [ -s "$TUJUAN/$berkas" ]; then
        echo "$berkas: ADA"
    else
        echo "$berkas: HILANG ATAU KOSONG"
        exit 1
    fi
done

rm -rf "$TUJUAN"

Output yang Dihasilkan:

text
backup_manifest
base.tar.gz
pg_wal.tar.gz
backup_manifest: ADA
base.tar.gz: ADA
pg_wal.tar.gz: ADA

Format tar memisahkan seluruh data directory ke dalam base.tar.gz, sementara WAL hasil -Xs dikemas sendiri sebagai pg_wal.tar.gz. Untuk memakai hasil ini, arsip harus diekstrak dulu (tar -xzf base.tar.gz ke direktori kosong, lalu tar -xzf pg_wal.tar.gz ke pg_wal/ di dalamnya) — satu langkah ekstra dibanding format plain yang langsung jadi data directory siap pakai. Kompresi -z menekan ukuran di disk, tetapi menambah beban CPU saat backup dibuat dan dipulihkan.

Ringkasan dua format dan implikasinya:

Aspek-Fp (plain)-Ft (tar)
Bentuk hasilstruktur direktori seperti data directoryfile arsip base.tar[.gz]
Langkah pemulihanlangsung dipakai sebagai PGDATAekstrak tar dulu
Kompresitidak ada (gunakan -Z/--compress saat streaming)-z gzip, atau -Z dengan tingkat tertentu
Cocok untukrestore cepat, disk cukup besararsip jangka panjang, transfer jarak jauh

Strategi Penanganan WAL: -Xs, -Xf, -Xn #

Satu pertanyaan menentukan mutu base backup: bagaimana WAL yang dibutuhkan backup ikut terkumpul? Opsi -X/--wal-method menyediakan tiga jawaban:

MetodeCara kerjaSifat hasil backup
-Xs (stream)WAL di-stream paralel sejak awal backupmandiri — semua WAL yang dibutuhkan ada di dalamnya
-Xf (fetch)WAL dikumpulkan di akhir, setelah file data selesai disalinbergantung WAL masih ada di server
-Xn (none)WAL tidak dikumpulkan sama sekalihanya konsisten bila disatukan dengan arsip WAL terpisah

Contoh-contoh chapter ini memakai -Xs karena hasilnya self-contained: salinan bisa dinyalakan langsung sebagai instance baru tanpa arsip WAL apa pun — sifat yang akan kita manfaatkan di chapter Menguji Prosedur Recovery .

Metode -Xn hanya relevan bila Anda menjalankan pengarsipan WAL kontinu (lihat chapter Point-in-Time Recovery ) dan ingin backup sekecil mungkin — WAL akan dipasok dari arsip saat pemulihan, bukan dari dalam backup.

Checkpoint: fast atau spread #

Sesaat sebelum penyalinan dimulai, pg_basebackup memaksa server menjalankan checkpoint — titik di mana semua halaman kotor sudah ditulis ke file data. Dua moda tersedia lewat --checkpoint:

ModaPerilakuKonsekuensi
fastcheckpoint penuh dijalankan segerabeban I/O menumpuk sesaat; backup cepat dimulai dan selesai
spreadcheckpoint disebar selama beberapa saatbeban halus bagi query online; backup baru mulai setelah checkpoint tuntas

Semua contoh kita memakai fast karena server latihan kecil dan durasi backup singkat. Di server produksi yang sibuk, spread sering dipilih supaya checkpoint dadakan tidak menambah lonjakan latensi bagi pengguna.

Menyiapkan Standby dengan -R #

Opsi -R mengubah base backup menjadi calon standby yang siap menyala: pg_basebackup menulis file standby.signal dan menambahkan primary_conninfo ke postgresql.auto.conf hasil backup. Skrip berikut memperlihatkan kedua artefak itu:

#!/usr/bin/env bash
# Base backup yang sekaligus siap dijadikan standby (-R).
set -euo pipefail

TUJUAN=/tmp/pgtutor-bb/standby

rm -rf "$TUJUAN"

# -R menulis standby.signal + primary_conninfo agar backup
# bisa langsung dinyalakan sebagai replika.
PGDATABASE=postgres pg_basebackup -D "$TUJUAN" -Fp -Xs --checkpoint=fast \
    -R --no-password

# Artefak pertama: file sinyal standby.
if [ -f "$TUJUAN/standby.signal" ]; then
    echo "standby.signal: ADA"
fi

# Artefak kedua: parameter koneksi ke server utama di postgresql.auto.conf.
grep primary_conninfo "$TUJUAN/postgresql.auto.conf"

rm -rf "$TUJUAN"

Output yang Dihasilkan:

text
standby.signal: ADA
primary_conninfo = 'user=postgres passfile=''/home/z/.pgpass'' channel_binding=prefer host=''/home/z/my-project/pgrun'' port=54329 sslmode=prefer sslnegotiation=postgres sslcompression=0 sslcertmode=allow sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres gssdelegation=0 target_session_attrs=any load_balance_hosts=disable dbname=postgres'

Baris primary_conninfo pada output berisi parameter koneksi lengkap ke server sumber — user, host (socket Unix server latihan), port, hingga sslmode — diambil dari koneksi yang dipakai pg_basebackup. Setelah backup seperti ini dinyalakan dengan pg_ctl, server baru langsung menjalankan mode standby dan menarik WAL dari server utama. Mekanisme streaming penuhnya dibahas di chapter Streaming Replication .

Opsi satu keluarga yang bernilai diketahui: --slot=nama_slot memakai replication slot agar server utama menahan WAL sampai backup selesai mengambilnya — menghapus jendela kegagalan -Xf; sementara --create-slot membuat slot itu seperlunya. Detail slot dibahas di chapter Replication Slot .

Verifikasi Backup dengan Manifest #

Base backup yang tersimpan berbulan-bulan bisa rusak diam-diam oleh sektor disk gagal atau transfer yang terputus. File backup_manifest memungkinkan pemeriksaan menyeluruh tanpa menyentuh server: pg_verifybackup membaca manifest, menghitung ulang checksum setiap file, dan memastikan manifest memuat WAL yang cukup untuk mencapai keadaan konsisten:

#!/usr/bin/env bash
# Verifikasi base backup memakai backup_manifest.
set -euo pipefail

TUJUAN=/tmp/pgtutor-bb/verifikasi

rm -rf "$TUJUAN"

pg_basebackup -D "$TUJUAN" -Fp -Xs --checkpoint=fast --no-password

# pg_verifybackup mencocokkan checksum setiap file dengan manifest,
# lalu memastikan manifest memuat WAL yang cukup untuk konsistensi.
pg_verifybackup "$TUJUAN"

rm -rf "$TUJUAN"

Output yang Dihasilkan:

text
backup successfully verified

Satu baris backup successfully verified berarti setiap byte cocok dengan manifest. Verifikasi seperti ini sebaiknya dijalankan segera setelah backup dibuat dan sekali lagi setelah backup dipindahkan ke lokasi penyimpanan jangka panjang — dua momen ketika kerusakan paling mungkin masuk.

Base backup memberi kita salinan utuh cluster pada satu momen. Pertanyaan berikutnya adalah bagaimana server menjamin setiap perubahan setelah momen itu tidak hilang — dan jawabannya adalah WAL, log tulis-dahulu yang menjadi bahan bakar seluruh pemulihan. Kita bedah mekanismenya di chapter Write-Ahead Logging .

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

backup-plain.sh

Unduh berkas
bash
#!/usr/bin/env bash
# Base backup format plain dengan WAL yang di-stream sekaligus.
set -euo pipefail

TUJUAN=/tmp/pgtutor-bb/plain

# Selalu mulai dari direktori kosong: pg_basebackup menolak direktori berisi.
rm -rf "$TUJUAN"

# -Fp  : format plain, struktur data directory disalin apa adanya
# -Xs  : WAL yang dibutuhkan backup ikut di-stream, backup jadi mandiri
# --checkpoint=fast : checkpoint dijalankan segera supaya backup cepat dimulai
pg_basebackup -D "$TUJUAN" -Fp -Xs --checkpoint=fast --no-password

# Struktur level atas hasil backup harus mencerminkan data directory.
ls -1 "$TUJUAN"

# backup_label menandai backup sah dan mencatat posisi WAL awal.
if [ -f "$TUJUAN/backup_label" ]; then
    echo "backup_label: ADA"
fi

# Versi mayor server yang dibackup.
cat "$TUJUAN/PG_VERSION"

# Selesai: hapus artefak lab.
rm -rf "$TUJUAN"

backup-standby.sh

Unduh berkas
bash
#!/usr/bin/env bash
# Base backup yang sekaligus siap dijadikan standby (-R).
set -euo pipefail

TUJUAN=/tmp/pgtutor-bb/standby

rm -rf "$TUJUAN"

# -R menulis standby.signal + primary_conninfo agar backup
# bisa langsung dinyalakan sebagai replika.
PGDATABASE=postgres pg_basebackup -D "$TUJUAN" -Fp -Xs --checkpoint=fast \
    -R --no-password

# Artefak pertama: file sinyal standby.
if [ -f "$TUJUAN/standby.signal" ]; then
    echo "standby.signal: ADA"
fi

# Artefak kedua: parameter koneksi ke server utama di postgresql.auto.conf.
grep primary_conninfo "$TUJUAN/postgresql.auto.conf"

rm -rf "$TUJUAN"

backup-tar.sh

Unduh berkas
bash
#!/usr/bin/env bash
# Base backup format tar dengan kompresi gzip.
set -euo pipefail

TUJUAN=/tmp/pgtutor-bb/tar

rm -rf "$TUJUAN"

# -Ft : format tar, hasil berupa file arsip
# -z  : kompresi gzip untuk setiap arsip
# -Xs : WAL dikemas sebagai arsip terpisah pg_wal.tar.gz
pg_basebackup -D "$TUJUAN" -Ft -z -Xs --checkpoint=fast --no-password

# Format tar selalu menghasilkan kombinasi file ini.
ls -1 "$TUJUAN"

# Pastikan ketiga arsip benar-benar berisi (ukuran lebih dari nol).
for berkas in backup_manifest base.tar.gz pg_wal.tar.gz; do
    if [ -s "$TUJUAN/$berkas" ]; then
        echo "$berkas: ADA"
    else
        echo "$berkas: HILANG ATAU KOSONG"
        exit 1
    fi
done

rm -rf "$TUJUAN"

prasyarat.sql

Unduh berkas
sql
-- pg_basebackup bekerja lewat protokol replikasi, bukan SQL biasa.
-- Tiga parameter ini menentukan apakah base backup bisa berjalan.
SHOW wal_level;

SHOW max_wal_senders;

SHOW wal_segment_size;

verifikasi-manifest.sh

Unduh berkas
bash
#!/usr/bin/env bash
# Verifikasi base backup memakai backup_manifest.
set -euo pipefail

TUJUAN=/tmp/pgtutor-bb/verifikasi

rm -rf "$TUJUAN"

pg_basebackup -D "$TUJUAN" -Fp -Xs --checkpoint=fast --no-password

# pg_verifybackup mencocokkan checksum setiap file dengan manifest,
# lalu memastikan manifest memuat WAL yang cukup untuk konsistensi.
pg_verifybackup "$TUJUAN"

rm -rf "$TUJUAN"