Backup & Recovery — Database

Mengapa Backup Penting? Data adalah aset paling berharga. Tanpa backup, satu kesalahan bisa menghilangkan semua data. Backup bukan optional — ini wajib. Jenis…

Backup adalah salinan database yang disimpan terpisah, supaya data bisa dikembalikan (restore atau recovery) setelah hilang atau rusak: disk mati, server dihapus, atau seseorang menjalankan DELETE tanpa WHERE. Bayangin buku kas Kedai Senja difotokopi setiap tengah malam. Jam 14:30 buku aslinya ketumpahan kopi. Kamu bisa menyalin ulang dari fotokopi semalam, tapi semua transaksi sejak tengah malam hilang, kecuali kamu juga menyimpan struk-struknya. Fotokopi itu full backup, dan tumpukan struk itu log perubahan.

🧪 Tebakan cepat: Kedai Senja di-backup penuh setiap pukul 00:00. Hari ini sampai pukul 14:29 ada 7 pesanan, 4 di antaranya masuk setelah tengah malam. Pukul 14:30 seseorang menjalankan DELETE FROM orders; (lupa WHERE). Setelah restore dari backup 00:00, berapa pesanan yang kembali? Tebak dulu, jawabannya ada di bagian "RPO dan RTO".

Satu hari di Kedai Senja

Lab di halaman ini memutar hari ini di SQLite sungguhan:

Jam Kejadian
00:00 full backup: 3 pelanggan, 4 produk, 3 pesanan (#1 sampai #3)
07:20 pesanan #4: Andi, 1 Teh Tarik
09:15 pesanan #5: Siti, 2 Kopi Susu Aren
11:40 pesanan #6: Budi, 1 Roti Bakar
13:05 harga Roti Bakar naik dari 20.000 jadi 22.000
14:10 pesanan #7: Budi, 1 Kopi Susu
14:30 DELETE FROM orders; semua pesanan hilang

RPO dan RTO

Dua angka yang harus kamu sepakati dengan pemilik bisnis sebelum bencana:

Backup penuh cuma pukul 00:00 berarti titik pulihnya 00:00. Yang kembali cuma 3 pesanan (#1 sampai #3). Pesanan #4 sampai #7 dan kenaikan harga Roti Bakar hilang: data 14 jam 30 menit lenyap. Itu jawaban tebakannya. Backup harian berarti RPO sampai 24 jam, dan untuk toko online itu biasanya terlalu besar.

Full, incremental, differential

Supaya RPO lebih kecil, backup harus lebih sering. Menyalin seluruh database setiap jam itu berat, jadi ada tiga jenis:

Di Lab, full pukul 00:00 lalu backup kecil pukul 04:00, 08:00 dan 12:00:

Backup Incremental berisi Differential berisi
04:00 0 perubahan 0 perubahan
08:00 #4 #4
12:00 #5, #6 #4, #5, #6

PITR: kembali ke detik sebelum bencana

PostgreSQL menulis setiap perubahan ke WAL (Write-Ahead Log) sebelum menerapkannya ke tabel. Kalau file WAL itu terus diarsip, kamu bisa melakukan PITR (Point-in-Time Recovery): pasang base backup, lalu putar ulang WAL sampai detik yang kamu pilih.

# postgresql.conf di server yang di-restore (PostgreSQL 12 ke atas)
restore_command = 'cp /backup/wal/%f %p'
recovery_target_time = '2026-10-08 14:29:59'
# lalu buat file kosong recovery.signal di folder data, dan nyalakan server

Alat PostgreSQL: pg_dump dan pg_basebackup

# logical backup: file SQL berisi CREATE TABLE dan semua datanya
pg_dump -h localhost -U postgres mydb > backup.sql
# restore-nya: jalankan file SQL itu
psql mydb < backup.sql

# physical backup: salinan file data PostgreSQL apa adanya
pg_basebackup -D /backup/base -Ft -z -P

# arsip WAL terus-menerus (postgresql.conf), syarat PITR
archive_mode = on
archive_command = 'cp %p /backup/wal/%f'

Cara memilih, persis seperti di latihan:

Ukuran database Boleh lama down saat restore? Pilihan
kecil (di bawah 1 GB) apa saja pg_dump
sedang (1 sampai 100 GB) boleh pg_dump
sedang (1 sampai 100 GB) tidak boleh pg_basebackup
besar (di atas 100 GB) apa saja pg_basebackup + WAL archiving

Backup yang gak pernah dites bukan backup

Bayangin job backup yang salah setting: perintahnya pg_dump --schema-only, jadi filenya cuma berisi CREATE TABLE tanpa satu baris data pun. File muncul setiap malam, job-nya "sukses", dan gak ada yang curiga sampai hari bencana. Satu-satunya cara tahu adalah restore drill: secara rutin (misalnya sebulan sekali) restore backup ke server terpisah, lalu cek isinya:

SELECT (SELECT COUNT(*) FROM customers) AS customers,
       (SELECT COUNT(*) FROM orders) AS orders;

Bandingkan dengan production. Waktu yang dibutuhkan drill itu juga RTO-mu yang sebenarnya. Simpan salinannya dengan aturan 3-2-1: 3 salinan data, di 2 media berbeda, 1 di luar lokasi (offsite). Pasang alert kalau job backup gagal atau ukuran filenya tiba-tiba mengecil.

⚠️ Jebakan yang sering ketemu

TL;DR: Backup adalah salinan terpisah untuk restore setelah data hilang atau rusak. RPO adalah berapa banyak data terakhir yang boleh hilang, RTO adalah berapa lama aplikasi boleh mati. Full backup menyalin seluruh database; incremental cuma perubahan sejak backup terakhir apa pun (restore butuh semua file berurutan); differential semua perubahan sejak full terakhir (restore cukup full + differential terakhir). PITR memutar ulang WAL dari base backup sampai detik sebelum bencana. Di PostgreSQL: pg_dump untuk database kecil atau yang boleh lama down saat restore, pg_basebackup untuk database sedang yang gak boleh lama down, pg_basebackup + WAL archiving untuk database besar. Simpan 3-2-1, dan jalankan restore drill rutin: backup yang gak pernah dites bukan backup.

Yang akan kamu pelajari