PostgreSQL — backup i restore bazy danych
Opublikowano: 9 kwietnia 2026 · Kategoria: Bazy danych
Brak backupu to nie ryzyko — to pewność utraty danych, to tylko kwestia czasu. PostgreSQL
dostarcza kilka narzędzi do tworzenia kopii zapasowych: od prostego pg_dump po zaawansowany
Point-in-Time Recovery z WAL archivingiem. Ten artykuł przeprowadzi cię przez każde z nich.
pg_dump — logiczny backup pojedynczej bazy
pg_dump to najprostsze narzędzie — tworzy spójny snapshot bazy bez blokowania innych
połączeń (używa transakcji REPEATABLE READ):
# Plain SQL — przenośny, edytowalny pg_dump -U postgres -d mydb > /backups/mydb_$(date +%Y%m%d_%H%M%S).sql # Custom format — skompresowany, szybszy restore, selektywny pg_dump -U postgres -Fc -d mydb -f /backups/mydb_$(date +%Y%m%d_%H%M%S).dump # Custom format z kompresją poziomu 9 pg_dump -U postgres -Fc -Z 9 -d mydb -f /backups/mydb.dump # Tylko schemat (bez danych) pg_dump -U postgres -s -d mydb > /backups/schema.sql # Tylko dane (bez schematu) pg_dump -U postgres -a -d mydb > /backups/data.sql # Tylko wybrane tabele pg_dump -U postgres -t users -t orders -d mydb > /backups/partial.sql
pg_restore — przywracanie z custom format
# Przywróć do istniejącej bazy pg_restore -U postgres -d mydb /backups/mydb.dump # Utwórz nową bazę i przywróć createdb -U postgres mydb_restore pg_restore -U postgres -d mydb_restore /backups/mydb.dump # Równoległy restore (4 wątki) — znacznie szybszy dla dużych baz pg_restore -U postgres -j 4 -d mydb_restore /backups/mydb.dump # Przywróć tylko wybraną tabelę pg_restore -U postgres -t users -d mydb_restore /backups/mydb.dump # Podejrzyj zawartość backupu bez przywracania pg_restore --list /backups/mydb.dump # Przywróć plain SQL psql -U postgres -d mydb < /backups/mydb.sql
pg_dumpall — backup wszystkich baz i użytkowników
pg_dumpall tworzy jeden plik SQL z wszystkimi bazami, rolami, tablespace'ami i ustawieniami
globalnymi. Niezbędny przy migracji całego serwera:
# Backup wszystkiego (bazy + role + tablespaces) pg_dumpall -U postgres > /backups/all_databases_$(date +%Y%m%d).sql # Tylko globalne obiekty (role, tablespaces) — bez danych pg_dumpall -U postgres -g > /backups/globals.sql # Przywróć psql -U postgres -f /backups/all_databases.sql
pg_basebackup — fizyczny backup dla PITR
Fizyczny backup kopiuje pliki danych PostgreSQL — jest podstawą replikacji strumieniowej i Point-in-Time Recovery:
# Wymaganie: użytkownik z uprawnieniem REPLICATION createuser -U postgres --replication backup_user # Fizyczny backup do katalogu pg_basebackup -U backup_user -D /backups/basebackup -Fp -Xs -P # Format tar z kompresją pg_basebackup -U backup_user -D /backups/basebackup -Ft -z -P # Opcje: # -Fp = plain format (katalog) # -Ft = tar format # -Xs = streaming WAL podczas backupu # -z = kompresja gzip # -P = progress bar
Automatyzacja backupów przez cron
#!/bin/bash
# /usr/local/bin/pg-backup.sh
BACKUP_DIR="/backups/postgresql"
DB_NAME="mydb"
DB_USER="postgres"
RETENTION_DAYS=30
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p ${BACKUP_DIR}
# Backup
pg_dump -U ${DB_USER} -Fc -Z 6 -d ${DB_NAME} \
-f "${BACKUP_DIR}/${DB_NAME}_${DATE}.dump"
# Sprawdź czy backup się udał
if [ $? -eq 0 ]; then
echo "Backup OK: ${DB_NAME}_${DATE}.dump"
else
echo "BŁĄD backupu ${DB_NAME}" | mail -s "PostgreSQL backup FAILED" [email protected]
exit 1
fi
# Usuń backupy starsze niż 30 dni
find ${BACKUP_DIR} -name "*.dump" -mtime +${RETENTION_DAYS} -delete chmod +x /usr/local/bin/pg-backup.sh # Dodaj do crontab (jako użytkownik postgres lub root) crontab -e # Backup codziennie o 2:00 w nocy 0 2 * * * /usr/local/bin/pg-backup.sh >> /var/log/pg-backup.log 2>&1
Strategia 3-2-1 dla PostgreSQL
- 3 kopie danych — oryginał na serwerze produkcyjnym + 2 kopie zapasowe.
- 2 różne nośniki/lokalizacje — np. lokalny dysk serwera i zdalny obiektowy storage (S3, Backblaze B2, Hetzner Storage Box).
- 1 kopia off-site — geograficznie oddalona od serwera głównego (chroni przed pożarem, zalaniem, awarią centrum danych).
# Kopiowanie backupu na zdalny storage (rclone + S3-compatible) rclone copy /backups/postgresql/ remote:my-bucket/postgresql/ # Lub przez rsync na inny serwer rsync -az /backups/postgresql/ backup-server:/backups/postgresql/
PITR — Point-in-Time Recovery
PITR pozwala przywrócić bazę do dowolnego momentu — np. 5 minut przed błędnym DELETE FROM orders. Wymaga WAL archivingu:
# postgresql.conf — włącz WAL archiving wal_level = replica archive_mode = on archive_command = 'cp %p /wal_archive/%f' # %p = ścieżka do segmentu WAL, %f = nazwa pliku
# Przywróć: basebackup + WAL do wybranego momentu # 1. Przywróć fizyczny backup tar -xzf /backups/base.tar.gz -C /var/lib/postgresql/data/ # 2. Utwórz recovery.conf (PostgreSQL < 12) lub postgresql.conf (12+) # recovery_target_time = '2026-04-09 14:30:00' # restore_command = 'cp /wal_archive/%f %p' # W PostgreSQL 12+ dodaj do postgresql.conf: # restore_command = 'cp /wal_archive/%f %p' # recovery_target_time = '2026-04-09 14:30:00' # Oraz utwórz pusty plik recovery.signal touch /var/lib/postgresql/data/recovery.signal # Następnie uruchom PostgreSQL — odtworzy WAL do wskazanego czasu
Uwaga: WAL archiving zwiększa I/O i zajmuje dysk. Monitoruj rozmiar katalogu archiwum i regularnie czyść stare segmenty (po pomyślnym backupie bazowym).