pg_dump dari chapter sebelumnya mengamankan isi satu database dengan rapi — tetapi chapter Konsep Backup
sudah memperingatkan lubangnya: role, kata sandi, dan daftar database tidak ikut di dalam file dump. Bayangkan memulihkan seluruh server dari dump per-database, lalu bangun di hadapan server baru yang tidak punya satu pun akun login — aplikasi menolak tersambung sebelum satu tabel pun dipulihkan. pg_dumpall menutup lubang itu: satu perintah ini menyapu seluruh cluster, dari role dan tablespace sampai isi tiap database, menjadi satu file SQL. Chapter ini membahasnya dari dua sisi: cadangan globals murni yang berjalan tiap malam, dan cadangan seluruh cluster yang menjadi rencana pemulihan bencana Anda.
Menyelam Satu Level ke Bawah #
Secara mekanisme, pg_dumpall adalah pembungkus yang bekerja dua lapis. Pertama, program ini membaca katalog cluster — pg_authid untuk role, pg_tablespace untuk tablespace, pg_database untuk daftar database — dan menuliskannya sebagai pernyataan CREATE ROLE, CREATE TABLESPACE, dan CREATE DATABASE. Kedua, untuk setiap database yang bisa dihubungi, pg_dumpall memanggil mesin pg_dump yang sama dari chapter sebelumnya dan menempelkan hasilnya ke file yang sama. Keluarannya selalu format plain SQL — tidak ada opsi custom atau directory di sini — sehingga pemulihannya selalu lewat psql.
Dua konsekuensi praktis dari mekanisme itu. Pertama, pg_dumpall perlu membaca hash kata sandi dari pg_authid, sesuatu yang hanya boleh dibaca superuser — praktisnya jalankan program ini sebagai postgres atau role superuser lain. Kedua, ukuran file keluarannya adalah seluruh cluster: semua database dijumlahkan, jadi pada server besar file ini bisa menjadi sangat besar dan prosesnya panjang — alasan pola hybrid di akhir chapter ini lahir.
–globals-only: Cadangan Role dan Tablespace #
Opsi --globals-only menghentikan pg_dumpall setelah lapis pertama: hanya role, tablespace, dan pengaturan tingkat cluster yang ditulis — tanpa menyentuh satu byte data pun. Skrip berikut membuat dua role demo, membandingkan keluaran biasa dengan varian --clean --if-exists, lalu membersihkan bekasnya:
#!/bin/bash
# Dua role tetap khusus demonstrasi.
psql -X -d postgres -v ON_ERROR_STOP=1 \
-c "DROP ROLE IF EXISTS bk_operator" \
-c "DROP ROLE IF EXISTS bk_pelaporan" \
-c "CREATE ROLE bk_operator LOGIN" \
-c "CREATE ROLE bk_pelaporan LOGIN" > /dev/null
# --globals-only: hanya role dan tablespace, tanpa data database sama sekali.
pg_dumpall --globals-only | grep '^CREATE ROLE bk_'
# Varian --clean --if-exists: siap diputar ulang di cluster yang sudah terisi.
pg_dumpall --globals-only --clean --if-exists \
| grep -E '^(DROP ROLE IF EXISTS|CREATE ROLE) bk_'
# Bersih-bersih role demo.
psql -X -d postgres -c "DROP ROLE bk_operator" -c "DROP ROLE bk_pelaporan" > /dev/nullOutput yang Dihasilkan:
CREATE ROLE bk_operator;
CREATE ROLE bk_pelaporan;
DROP ROLE IF EXISTS bk_operator;
DROP ROLE IF EXISTS bk_pelaporan;
CREATE ROLE bk_operator;
CREATE ROLE bk_pelaporan;Bedah skripnya langkah demi langkah:
- Empat perintah
-cpertama: menyiapkan keadaan awal yang deterministik —DROP ROLE IF EXISTSdua kali membuang sisa percobaan lama, lalu duaCREATE ROLE ... LOGINmembuat role demo. Seluruh keluarannya dibuang ke/dev/nullkarena tagCREATE ROLEitu bukan pokok bahasan. pg_dumpall --globals-only | grep '^CREATE ROLE bk_': file globals berisi seluruh role di cluster, jadigrepmenyaring hanya role demo kita agar keluaran contoh tetap fokus — dua barisCREATE ROLE bk_operator;danCREATE ROLE bk_pelaporan;.- Varian
--clean --if-exists: keluarannya didahuluiDROP ROLE IF EXISTSuntuk tiap role. Tanpa opsi ini, memutar ulang file globals di cluster yang rolenya sudah ada akan berakhir error duplikat; dengan opsi ini file menjadi idempoten — aman dijalankan berulang di atas keadaan apa pun.
Role yang memiliki kata sandi ditulis lengkap dengan hash-nya: CREATE ROLE ... PASSWORD 'SCRAM-SHA-256$...'. String hash itu berisi salt acak yang dibuat saat kata sandi diubah, dan satu-satunya cara mendapatkannya adalah membaca pg_authid — superuser saja yang bisa. Opsi --no-role-passwords sengaja membuang bagian ini bila file globals harus dibagikan tanpa membocorkan verifikasi sandi.
Cadangan Seluruh Cluster #
Tanpa penyaringan apa pun, pg_dumpall menulis semuanya. Skrip berikut membuktikan cakupannya dengan membuat satu database tambahan yang pasti ikut tersapu:
#!/bin/bash
pg_dumpall --version
# Satu database tambahan tetap untuk membuktikan cakupan cluster.
psql -X -d postgres -v ON_ERROR_STOP=1 \
-c "DROP DATABASE IF EXISTS bk_gudang WITH (FORCE)" \
-c "CREATE DATABASE bk_gudang" > /dev/null
# Satu perintah, seluruh cluster: semua database, semua role, semuanya.
# --exclude-database membuang database sementara latihan (pgtutor_*, probe_*)
# agar cadangan hanya berisi database yang dimaksudkan.
pg_dumpall --exclude-database 'pgtutor_*' --exclude-database 'probe_*' \
> backup_cluster.sql
# Bukti cakupan: database bk_gudang ikut di dalam file.
grep '^CREATE DATABASE bk_gudang' backup_cluster.sql
# File demo dihapus agar bundel contoh tetap ringkas;
# di lingkungan nyata file inilah aset terpenting Anda.
rm backup_cluster.sql
# Bersih-bersih database demo.
psql -X -d postgres -c "DROP DATABASE bk_gudang WITH (FORCE)" > /dev/nullOutput yang Dihasilkan:
pg_dumpall (PostgreSQL) 17.11 (Debian 17.11-0+deb13u1)
CREATE DATABASE bk_gudang WITH TEMPLATE = template0 ENCODING = 'UTF8' LOCALE_PROVIDER = libc LOCALE = 'C';Tiga pengamatan dari keluarannya. Pertama, pg_dumpall --version melaporkan versi alat yang dipakai — informasi yang menentukan kompatibilitas (dibahas di bawah). Kedua, grep menemukan baris CREATE DATABASE bk_gudang WITH TEMPLATE = template0 ... di dalam file: bukti bahwa bahkan database yang dibuat sepersekian detik sebelum dump ikut tersapu, lengkap dengan pengaturan encoding dan locale aslinya. Ketiga, opsi --exclude-database menerima pola nama dan bisa diulang — di lingkungan uji materi ini pola pgtutor_* dan probe_* membuang database latihan sementara yang tercipta dan terhapus saat chapter diuji; di produksi pola yang sama lazim dipakai membuang database staging atau uji dari cadangan cluster. Terakhir, skrip sengaja menghapus backup_cluster.sql di akhir — file cluster berisi seluruh isi server Anda dan isinya berubah setiap kali dijalankan; di produksi file inilah yang dikompres, dienkripsi, dan dikirim ke penyimpanan offsite sesuai aturan 3-2-1.
Pemulihannya satu langkah: di cluster kosong yang baru, jalankan psql -X -d postgres -f backup_cluster.sql sebagai superuser. File berjalan berurutan — role dibuat dulu, lalu tiap database dibuat dan diisikan — sehingga di akhirnya cluster baru menyerupai aslinya lengkap dengan akun login. Varian --clean --if-exists pada seluruh cluster bekerja dengan cara yang sama seperti pada globals: tiap objek dijatuhkan dulu sehingga file aman diputar ulang di cluster yang sudah berisi.
Pola Malam Hari: globals Tiap Hari, Dump per Database #
Karena file cluster besar dan tidak bisa dipulihkan selektif, praktik umum di lapangan memecah pekerjaan menjadi dua:
| Pekerjaan | Frekuensi lazim | Alat | Hasil |
|---|---|---|---|
| Cadangkan globals (role, tablespace) | tiap malam | pg_dumpall --globals-only | satu file kecil |
| Cadangkan tiap database | tiap malam, paralel | pg_dump -Fc per database | satu file dump per database |
Pola hybrid ini memberi tiga keuntungan: file dump per-database bisa dipulihkan sendirian (RTO lebih pendek untuk insiden satu aplikasi), beberapa dump bisa berjalan paralel untuk cluster berisi banyak database, dan format -Fc membuka pintu pemulihan selektif lewat pg_restore. Globals tetap dicadangkan tiap malam karena berubah jarang tapi fatal bila hilang — dan filenya kecil sekali. Jadwal dan retensi pola ini dibahas penuh di chapter Backup Scheduling
.
Catatan Versi #
Aturan kompatibilitasnya sederhana: gunakan pg_dumpall yang senewer atau lebih baru daripada server yang dicadangkan — versi baru tahu cara membaca katalog versi lama, tidak sebaliknya. Skenario tipikalnya: server produksi masih PostgreSQL 15 sementara mesin backup sudah terpasang PostgreSQL 17; pg_dumpall versi 17 boleh dipakai ke server 15 itu, dan hasilnya aman dipulihkan ke server versi 15 ke atas. Hindari arah yang berlawanan — versi lama tidak mengenal fitur katalog versi baru. Itulah sebabnya baris pg_dumpall --version di skrip sebelumnya layak dibiasakan sebagai pengecekan pertama setiap mesin backup baru disiapkan.
Satu file besar berisi seluruh cluster kini bisa Anda buat kapan pun — tetapi file format plain itu dipulihkan sekaligus atau tidak sama sekali. Untuk pemulihan yang bisa memilih: hanya satu tabel, hanya skema, atau dengan beberapa proses paralel — kita pergi ke alat pasangannya: pg_restore.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
cluster-demo.sh
Unduh berkas#!/bin/bash
pg_dumpall --version
# Satu database tambahan tetap untuk membuktikan cakupan cluster.
psql -X -d postgres -v ON_ERROR_STOP=1 \
-c "DROP DATABASE IF EXISTS bk_gudang WITH (FORCE)" \
-c "CREATE DATABASE bk_gudang" > /dev/null
# Satu perintah, seluruh cluster: semua database, semua role, semuanya.
# --exclude-database membuang database sementara latihan (pgtutor_*, probe_*)
# agar cadangan hanya berisi database yang dimaksudkan.
pg_dumpall --exclude-database 'pgtutor_*' --exclude-database 'probe_*' \
> backup_cluster.sql
# Bukti cakupan: database bk_gudang ikut di dalam file.
grep '^CREATE DATABASE bk_gudang' backup_cluster.sql
# File demo dihapus agar bundel contoh tetap ringkas;
# di lingkungan nyata file inilah aset terpenting Anda.
rm backup_cluster.sql
# Bersih-bersih database demo.
psql -X -d postgres -c "DROP DATABASE bk_gudang WITH (FORCE)" > /dev/null
globals-demo.sh
Unduh berkas#!/bin/bash
# Dua role tetap khusus demonstrasi.
psql -X -d postgres -v ON_ERROR_STOP=1 \
-c "DROP ROLE IF EXISTS bk_operator" \
-c "DROP ROLE IF EXISTS bk_pelaporan" \
-c "CREATE ROLE bk_operator LOGIN" \
-c "CREATE ROLE bk_pelaporan LOGIN" > /dev/null
# --globals-only: hanya role dan tablespace, tanpa data database sama sekali.
pg_dumpall --globals-only | grep '^CREATE ROLE bk_'
# Varian --clean --if-exists: siap diputar ulang di cluster yang sudah terisi.
pg_dumpall --globals-only --clean --if-exists \
| grep -E '^(DROP ROLE IF EXISTS|CREATE ROLE) bk_'
# Bersih-bersih role demo.
psql -X -d postgres -c "DROP ROLE bk_operator" -c "DROP ROLE bk_pelaporan" > /dev/null