Alene at have regelmæssige sikkerhedskopier af din PostgreSQL-database er ikke tilstrækkeligt til en hurtig gendannelse - du skal sikre, at sikkerhedskopieringsfilerne er tilgængelige og sunde, hvis og når det kræves for en gendannelsesprocedure. Læs videre for at se nogle eksempler på, hvordan du opsætter automatisk test af PostgreSQL-sikkerhedskopier.
Sikkerhedskopier lavet ved hjælp af pg_basebackup
pg_basebackup sikkerhedskopier indeholder hele databiblioteket for en databaseklynge. Denne mappe er normalt pakket sammen i en tarball, nogle gange med en ekstra tarball til WAL-filer, der er blevet oprettet siden starten af sikkerhedskopieringen.
For at teste sådan en pg_basebackup tarball, pakke først tarballen ud i en tom mappe. Hvis der er en separat WAL-fil tarball, skal du pakke den ud i pg_wal
mappe i den nye mappe:
$ mkdir backup-test
$ cd backup-test
$ tar --no-same-owner xvf /path/to/base.tar.gz
$ mkdir -p pg_wal
$ cd pg_wal
$ tar --no-same-owner xvf /path/to/pg_wal.tar.gz
Du kan nu starte en PostgreSQL-serverproces for denne mappe:
$ pg_ctl -D path/to/backup-test start
(Bemærk:pg_ctl er et kommandolinjeværktøj inkluderet i Postgres-standarddistributionen. Det er tilgængeligt overalt, hvor Postgres selv er, ligesom de andre inkluderede værktøjer såsom psql og pg_dump .Læs mere om pg_ctl her.)
Hvis der allerede er en PostgreSQL-server installeret/kører på denne maskine, vil du sandsynligvis starte på en anden port end standard 5432:
$ pg_ctl -D path/to/backup-test -o "-p 6000 -k /tmp" start
Hvis alt lykkedes indtil videre, vil du gerne kontrollere, om dataene i din gendannede database er fornuftige. Hvis du har automatiserede testscripts til at køre mod din database, ville det nu være et godt tidspunkt at starte mindst et lille sæt af disse tests mod denne gendannede database. Hvis ikke, kan du hacke nogle quickchecks sammen med psql:
$ psql -p 6000 -d mydb -o /dev/null -c "select * from users limit 1"
Ovenstående kommando laver en simpel forespørgsel mod en tabel, som burde eksistere. Udgangskoden for psql skulle fortælle dig, om forespørgslen var vellykket eller ej. Selvfølgelig kan du køre mere komplekse forespørgsler eller køre en .sql-fil eller endda et separat testscript, der forbinder til denne database og kører tests.
Når du er færdig med testen, kan du stoppe Postgres-serverprocessen med:
$ pg_ctl -D path/to/backup-test stop
Og ryd op i hele det udpakkede databaseklyngebibliotek:
$ rm -rf path/to/backup-test
Sådan ser det ud, når det hele er sat sammen:
#!/bin/bash
# exit immediately if any step fails
set -eo pipefail
# fetch the latest backup
# TODO: copy out base.tar.gz and pg_wal.tar.gz of latest backup
# create a directory to work in
BACKUP_DIR=/tmp/backup-test
rm -rf $BACKUP_DIR
mkdir $BACKUP_DIR
# unpack the backup archives
tar -C $BACKUP_DIR --no-same-owner xvf /path/to/base.tar.gz
mkdir -p $BACKUP_DIR/pg_wal
tar -C $BACKUP_DIR/pg_wal --no-same-owner xvf /path/to/pg_wal.tar.gz
# start a new Postgres server for the cluster on port 6000
pg_ctl -D $BACKUP_DIR -o "-p 6000 -k /tmp" start
# perform a simple test
psql -p 6000 -d mydb -o /dev/null -c "select * from users limit 1"
# shutdown the server
pg_ctl -D $BACKUP_DIR stop
# cleanup the files
rm -rf $BACKUP_DIR /path/to/base.tar.gz /path/to/pg_wal.tar.gz
Sikkerhedskopier lavet ved hjælp af pg_dump
pg_dump værktøj (dokumenter) kan også bruges til at lave sikkerhedskopier – dette er mere fleksibelt ved, at du valgfrit kan vælge den database/de skema/tabeller, du vil sikkerhedskopiere, i modsætning tilpg_basebackup hvilket er en alt-eller-intet-proces.
Med pg_dump , kan du generere en enkelt .sql
script eller en binær .pgdmp
fil, der indeholder alle data (og eventuelt også DDL-sætningerne til oprettelse af tabeller/indekser osv.). For at gendanne en sådan fil skal du oprette forbindelse til en livedatabaseserver og køre SQL-kommandoerne inde i .sql/.pgdmp-filen. Mens du kan bruge den almindelige psql for at køre .sql-filen skal du bruge pg_restore kommando (docs) for at køre .pgdmp-filen.
For at teste sådanne sikkerhedskopier henter vi først filen og opretter derefter en ny, tom databaseklynge:
$ rm -rf path/to/backup-test
$ pg_ctl -D path/to/backup-test initdb
og start en PostgreSQL-server på den, lyt på port 6000 som før:
$ pg_ctl -D path/to/backup-test -o "-p 6000 -k /tmp" start
Det er muligt at generere pg_dump filer, der er fuldt selvstændige, men det er også muligt at generere dem, så de ikke er det. Derfor, afhængigt af hvordan dumpet blev genereret, kan nogle opsætningstrin være nødvendige:
- opret en database
- opret tabeller, indekser osv.
- tildel privilegier
Når det er gjort, kan du enten bruge psql eller pg_restore for at bringe data tilbage til live:
# for .sql files
$ psql -p 6000 -h /tmp -v ON_ERROR_STOP=1 -1 -b -f path/to/dump.sql
# for .pgdmp files
$ pg_restore -p 6000 -h /tmp -d mydb -C -1 -f path/to/dump.pgdmp
Som før kan der på dette tidspunkt udføres test for at sikre, at de lagrede data er fornuftige.
Sådan ser det ud, alt sammen:
#!/bin/bash
# exit immediately if any step fails
set -eo pipefail
# fetch the latest dump
# TODO: copy out the dump.sql or dump.pgdmp of latest backup
# create an empty database cluster
BACKUP_DIR=/tmp/backup-test
rm -rf $BACKUP_DIR
pg_ctl -D $BACKUP_DIR initdb
# start a new Postgres server for the cluster on port 6000
pg_ctl -D $BACKUP_DIR -o "-p 6000 -k /tmp" start
# TODO: perform any specific setup steps here
# restore the file, .sql:
psql -p 6000 -h /tmp -v ON_ERROR_STOP=1 -1 -b -f path/to/dump.sql
# or .pgdmp:
pg_restore -p 6000 -h /tmp -d mydb -C -1 -f path/to/dump.pgdmp
# perform a simple test
psql -p 6000 -d mydb -o /dev/null -c "select * from users limit 1"
# shutdown the server
pg_ctl -D $BACKUP_DIR stop
# cleanup the files
rm -rf $BACKUP_DIR /path/to/dump.*
Pas på udløsere
Mens du gendanner en pg_dump sikkerhedskopiering, bliver data indsat i tabeller, ligesom når en applikation gør det. Hvis du har triggere, der forbinder til eksterne tjenester for at give besked om rækkeindsættelser, er det bedst at deaktivere dem under gendannelsesproceduren.
Når du kalder pg_dump for at udsende sql-filer, kan du bruge muligheden--disable-triggers
at fortælle pg_dump for at generere script for at deaktivere triggerne under indsættelse.
Når du kalder pg_restore på en database, der allerede har triggere, kan du bruge --disable-triggers
i pg_restore for at opnå samme effekt.
PITR-test
Point-in-time-recovery (PITR) i Postgres er afhængig af en fuld sikkerhedskopi taget ved hjælp afpg_basebackup , og en sekvens af WAL-filer fra det tidspunkt og frem til det tidspunkt, hvor du vil gendanne. Test af PITR indebærer derfor at teste den fulde backup såvel som de efterfølgende WAL-filer.
For automatisk sikkerhedskopieringstest har vi ikke et specifikt gendannelsesmål. Alle arkiverede WAL-filer fra sidste sikkerhedskopi og frem til den seneste bør testes. Den nemmeste måde at teste dette på er at følge de samme trin som for pg_basebackup testmetode, med kun et ekstra trin. Efter udpakning af den seneste sikkerhedskopi skal du hente alle relevante og tilgængelige WAL-filer og placere dem i pg_wal
før du starter Postgres-serveren. Specifikt:
#!/bin/bash
# exit immediately if any step fails
set -eo pipefail
# fetch the latest backup
# TODO: copy out base.tar.gz and pg_wal.tar.gz of latest backup
# create a directory to work in
BACKUP_DIR=/tmp/backup-test
rm -rf $BACKUP_DIR
mkdir $BACKUP_DIR
# unpack the backup archives
tar -C $BACKUP_DIR --no-same-owner xvf /path/to/base.tar.gz
mkdir -p $BACKUP_DIR/pg_wal
tar -C $BACKUP_DIR/pg_wal --no-same-owner xvf /path/to/pg_wal.tar.gz
# --> this is the new extra step <--
# TODO: fetch all WAL files from the WAL archive since the last
# backup, and place them in $BACKUP_DIR/pg_wal
# start a new Postgres server for the cluster on port 6000
pg_ctl -D $BACKUP_DIR -o "-p 6000 -k /tmp" start
# perform a simple test
psql -p 6000 -d mydb -o /dev/null -c "select * from users limit 1"
# shutdown the server
pg_ctl -D $BACKUP_DIR stop
# cleanup the files
rm -rf $BACKUP_DIR /path/to/base.tar.gz /path/to/pg_wal.tar.gz
Dette skal verificere, om både den sidste backup og efterfølgende WAL-filer er gode, så de kan bruges til PITR, hvis og når det er nødvendigt.