sql >> Database teknologi >  >> RDS >> PostgreSQL

Sikkerhedskopier PostgreSQL ved hjælp af pg_dump og pg_dumpall

Virksomheder og tjenester leverer værdi baseret på data. Tilgængelighed, ensartet tilstand og holdbarhed er topprioriteter for at holde kunder og slutbrugere tilfredse. Tabte eller utilgængelige data kan muligvis svare til mistede kunder.

Databasesikkerhedskopier bør være på forkant med daglig drift og opgaver.

Vi bør være forberedt på, at vores data bliver beskadiget eller går tabt.

Jeg tror fuldt og fast på et gammelt ordsprog, jeg har hørt:"Det er bedre at have det og ikke have brug for det end at have brug for det og ikke have det . "

Det gælder også for sikkerhedskopiering af databaser. Lad os se det i øjnene, uden dem har du dybest set ingenting. At operere ud fra den forestilling, at intet kan ske med dine data, er en fejlslutning.

De fleste DBMS'er giver nogle midler til indbyggede sikkerhedskopieringsværktøjer. PostgreSQL har pg_dump og pg_dumpall ud af æsken.

Begge præsenterer adskillige tilpasnings- og struktureringsmuligheder. At dække dem alle individuelt i ét blogindlæg ville være nærmest umuligt. I stedet vil jeg se på de eksempler, jeg bedst kan anvende til mit personlige udviklings-/læringsmiljø.

Når det så er sagt, er dette blogindlæg ikke målrettet et produktionsmiljø. Det er mere sandsynligt, at en enkelt arbejdsstation/udviklingsmiljø vil gavne mest.

Hvad er pg_dump og pg_dumpall?

Dokumentationen beskriver pg_dump som:"pg_dump er et værktøj til sikkerhedskopiering af en PostgreSQL-database"

Og pg_dumpall-dokumentationen:"pg_dumpall er et værktøj til at udskrive ("dumpe") alle PostgreSQL-databaser i en klynge til én scriptfil."

Sikkerhedskopiering af en database og/eller tabeller

Til at starte med vil jeg oprette en praksisdatabase og nogle tabeller til at arbejde med ved hjælp af nedenstående SQL:

postgres=# CREATE DATABASE example_backups;
CREATE DATABASE
example_backups=# CREATE TABLE students(id INTEGER,
example_backups(# f_name VARCHAR(20),
example_backups(# l_name VARCHAR(20));
CREATE TABLE
example_backups=# CREATE TABLE classes(id INTEGER,
example_backups(# subject VARCHAR(20));
CREATE TABLE
example_backups=# INSERT INTO students(id, f_name, l_name)
example_backups-# VALUES (1, 'John', 'Thorn'), (2, 'Phil', 'Hampt'),
example_backups-# (3, 'Sue', 'Dean'), (4, 'Johnny', 'Rames');
INSERT 0 4
example_backups=# INSERT INTO classes(id, subject)
example_backups-# VALUES (1, 'Math'), (2, 'Science'),
example_backups-# (3, 'Biology');
INSERT 0 3
example_backups=# \dt;
         List of relations
Schema |   Name | Type  | Owner
--------+----------+-------+----------
public | classes  | table | postgres
public | students | table | postgres
(2 rows)
example_backups=# SELECT * FROM students;
id | f_name | l_name
----+--------+--------
 1 | John   | Thorn
 2 | Phil   | Hampt
 3 | Sue    | Dean
 4 | Johnny | Rames
(4 rows)
example_backups=# SELECT * FROM classes;
id | subject
----+---------
 1 | Math
 2 | Science
 3 | Biology
(3 rows)

Database og tabeller er alle sat op.

Bemærk:

I mange af disse eksempler vil jeg drage fordel af psql's \! meta-kommando, som giver dig mulighed for enten at falde ind i en shell (kommando-linje) eller udføre de skalkommandoer, der følger efter.

Bare vær opmærksom på, at i en terminal- eller kommandolinjesession (angivet med en ledende '$' i dette blogindlæg), vil \! meta-kommando bør ikke inkluderes i nogen af ​​kommandoerne pg_dump eller pg_dumpall. Igen, det er en bekvemmeligheds-metakommando i psql.

Sikkerhedskopiering af en enkelt tabel

I dette første eksempel vil jeg dumpe den eneste elevtabel:

example_backups=# \! pg_dump -U postgres -t students example_backups > ~/Example_Dumps/students.sql.

Når vi viser mappens indhold, ser vi, at filen er der:

example_backups=# \! ls -a ~/Example_Dumps
.  .. students.sql

Kommandolinjeindstillingerne for denne individuelle kommando er:

  • -U postgres:det angivne brugernavn
  • -t elever:tabellen til at dumpe
  • example_backups:databasen

Hvad er der i students.sql-filen?

$ cat students.sql
--
-- PostgreSQL database dump
--
-- Dumped from database version 10.4 (Ubuntu 10.4-2.pgdg16.04+1)
-- Dumped by pg_dump version 10.4 (Ubuntu 10.4-2.pgdg16.04+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;
 
SET default_tablespace = '';
 
SET default_with_oids = false;
 
--
-- Name: students; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.students (
   id integer,
   f_name character varying(20),
   l_name character varying(20)
);
 
ALTER TABLE public.students OWNER TO postgres;
 
--
-- Data for Name: students; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public.students (id, f_name, l_name) FROM stdin;
1 John Thorn
2 Phil Hampt
3 Sue Dean
4 Johnny Rames
\.
--
-- PostgreSQL database dump complete

Vi kan se, at filen har de nødvendige SQL-kommandoer til at genskabe og genudfylde tabelelever.

Men er backupen god? Pålidelig og fungerende?

Vi vil teste det og se.

example_backups=# DROP TABLE students;
DROP TABLE
example_backups=# \dt;
         List of relations
Schema |  Name | Type  | Owner
--------+---------+-------+----------
public | classes | table | postgres
(1 row)

Det er væk.

Send derefter den gemte sikkerhedskopi fra kommandolinjen til psql:

$ psql -U postgres -W -d example_backups -f ~/Example_Dumps/students.sql
Password for user postgres:
SET
SET
SET
SET
SET
set_config
------------
(1 row)
 
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
COPY 4

Lad os verificere i databasen:

example_backups=# \dt;
         List of relations
Schema |   Name | Type  | Owner
--------+----------+-------+----------
public | classes  | table | postgres
public | students | table | postgres
(2 rows)
example_backups=# SELECT * FROM students;
id | f_name | l_name
----+--------+--------
 1 | John   | Thorn
 2 | Phil   | Hampt
 3 | Sue    | Dean
 4 | Johnny | Rames
(4 rows)

Tabel og data er blevet gendannet.

Sikkerhedskopiering af flere tabeller

I dette næste eksempel vil vi sikkerhedskopiere begge tabeller ved hjælp af denne kommando:

example_backups=# \! pg_dump -U postgres -W -t classes -t students -d example_backups > ~/Example_Dumps/all_tables.sql
Password:

(Bemærk, at jeg var nødt til at angive en adgangskode i denne kommando på grund af -W-indstillingen, hvor jeg ikke gjorde det i det første eksempel. Mere om dette kommer.)

Lad os igen bekræfte, at filen blev oprettet ved at angive bibliotekets indhold:

example_backups=# \! ls -a ~/Example_Dumps
.  .. all_tables.sql  students.sql

Slip derefter tabellerne:

example_backups=# DROP TABLE classes;
DROP TABLE
example_backups=# DROP TABLE students;
DROP TABLE
example_backups=# \dt;
Did not find any relations.

Gendan derefter med backupfilen all_tables.sql:

$ psql -U postgres -W -d example_backups -f ~/Example_Dumps/all_tables.sql
Password for user postgres:
SET
SET
SET
SET
SET
set_config
------------
(1 row)
 
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
COPY 3
COPY 4
example_backups=# \dt;
         List of relations
Schema |   Name | Type  | Owner
--------+----------+-------+----------
public | classes  | table | postgres
public | students | table | postgres
(2 rows)

Begge borde er blevet gendannet.

Som vi kan se med pg_dump, kan du sikkerhedskopiere kun én eller flere tabeller i en specifik database.

Sikkerhedskopiering af en database

Lad os nu se, hvordan du sikkerhedskopierer hele example_backups-databasen med pg_dump.

example_backups=# \! pg_dump -U postgres -W -d example_backups > ~/Example_Dumps/ex_back_db.sql
Password:
 
example_backups=# \! ls -a ~/Example_Dumps
.  .. all_tables.sql  ex_back_db.sql students.sql

Ex_back_db.sql-filen er der.

Jeg vil oprette forbindelse til postgres-databasen for at droppe example_backups-databasen.

postgres=# DROP DATABASE example_backups;
DROP DATABASE

Gendan derefter fra kommandolinjen:

$ psql -U postgres -W -d example_backups -f ~/Example_Dumps/ex_back_db.sql
Password for user postgres:
psql: FATAL:  database "example_backups" does not exist

Det er der ikke. Hvorfor ikke? Og hvor er det?

Vi skal skabe det først.

postgres=# CREATE DATABASE example_backups;
CREATE DATABASE

Gendan derefter med den samme kommando:

$ psql -U postgres -W -d example_backups -f ~/Example_Dumps/ex_back_db.sql
Password for user postgres:
SET
SET
SET
SET
SET
set_config
------------
(1 row)
 
SET
SET
SET
CREATE EXTENSION
COMMENT
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
COPY 3
COPY 4
postgres=# \c example_backups;
You are now connected to database "example_backups" as user "postgres".
example_backups=# \dt;
         List of relations
Schema |   Name | Type  | Owner
--------+----------+-------+----------
public | classes  | table | postgres
public | students | table | postgres
(2 rows)

Database og alle tabeller til stede og redegjort for.

Vi kan undgå dette scenarie med først at skulle oprette måldatabasen ved at inkludere -C-indstillingen, når du tager sikkerhedskopien.

example_backups=# \! pg_dump -U postgres -W -C -d example_backups > ~/Example_Dumps/ex_back2_db.sql
Password:

Jeg genopretter forbindelse til postgres-databasen og dropper example_backups-databasen, så vi kan se, hvordan gendannelsen fungerer nu (Bemærk, at disse connect- og DROP-kommandoer ikke vises for kortheds skyld).

Derefter på kommandolinjen (bemærk ingen -d dbname-indstilling inkluderet):

$ psql -U postgres -W -f ~/Example_Dumps/ex_back2_db.sql
Password for user postgres:
……………..
(And partway through the output...)
CREATE DATABASE
ALTER DATABASE
Password for user postgres:
You are now connected to database "example_backups" as user "postgres".
SET
SET
SET
SET
SET
set_config
------------
(1 row)
 
SET
SET
SET
CREATE EXTENSION
COMMENT
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
COPY 3
COPY 4

Ved at bruge -C-indstillingen bliver vi bedt om en adgangskode for at oprette en forbindelse som nævnt i dokumentationen vedrørende -C-flaget:

"Begynd outputtet med en kommando for at oprette selve databasen og genoprette forbindelsen til den oprettede database."

Så i psql-sessionen:

postgres=# \c example_backups;
You are now connected to database "example_backups" as user "postgres".

Alt er gendannet, godt i gang og uden behov for at oprette måldatabasen før gendannelsen.

pg_dumpall for hele klyngen

Indtil videre har vi sikkerhedskopieret en enkelt tabel, flere tabeller og en enkelt database.

Men hvis vi vil have mere end det, for eksempel at sikkerhedskopiere hele PostgreSQL-klyngen, er det dér, vi skal bruge pg_dumpall.

Så hvad er nogle bemærkelsesværdige forskelle mellem pg_dump og pg_dumpall?

For det første er her en vigtig sondring fra dokumentationen:

"Da pg_dumpall læser tabeller fra alle databaser, bliver du højst sandsynligt nødt til at oprette forbindelse som en database-superbruger for at producere et komplet dump. Du skal også bruge superbrugerrettigheder for at udføre det gemte script for at få lov til at tilføje brugere og grupper og oprette databaser."

Ved at bruge nedenstående kommando vil jeg sikkerhedskopiere hele min PostgreSQL-klynge og gemme den i filen whole_cluster.sql:

$ pg_dumpall -U postgres -W -f ~/Example_Dumps/Cluster_Dumps/entire_cluster.sql
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:

Hvad I alverden? Er du i tvivl om, om jeg skulle indtaste en adgangskode for hver prompt?

Ja, det gjorde det bestemt. 24 gange.

Tæl dem. (Hej, jeg kan godt lide at udforske og dykke ned i forskellige databaser, mens jeg lærer? Hvad kan jeg sige?)

Men hvorfor alle de opfordringer?

Først og fremmest, efter alt det hårde arbejde, oprettede pg_dumpall backup-filen?

postgres=# \! ls -a ~/Example_Dumps/Cluster_Dumps
.  .. entire_cluster.sql

Yep, backup-filen er der.

Lad os kaste lidt lys over al den 'tasteøvelse ved at se denne passage fra dokumentationen:

"pg_dumpall skal oprette forbindelse flere gange til PostgreSQL-serveren (én gang pr. database). Hvis du bruger adgangskodegodkendelse, vil den bede om en adgangskode hver gang.”

Jeg ved, hvad du tænker.

Dette er måske ikke ideelt eller endda muligt. Hvad med processer, scripts eller cron-job, der kører midt om natten?

Er der nogen, der vil svæve over tastaturet og vente på at skrive?

Sandsynligvis ikke.

En effektiv foranstaltning til at forhindre disse gentagne adgangskodeprompter er en ~/.pgpass-fil.

Her er den syntaks, som ~/.pgpass-filen kræver for at fungere (eksempel fra dokumentationen, se linket ovenfor):

hostname:port:database:username:password

Med en ~/.pgpass-fil til stede i mit udviklingsmiljø, der indeholder de nødvendige legitimationsoplysninger til postgres-rollen, kan jeg udelade indstillingen -W (også -w) og køre pg_dumpall uden manuelt at godkende med adgangskoden:

$ pg_dumpall -U postgres -f ~/Example_Dumps/Cluster_Dumps/entire_cluster2nd.sql

Visning af bibliotekets indhold:

postgres=# \! ls -a ~/Example_Dumps/Cluster_Dumps
.  .. entire_cluster2nd.sql  entire_cluster.sql

Filen er oprettet, og der bliver ikke bedt om gentagne adgangskoder.

Den gemte fil kan genindlæses med psql svarende til pg_dump.

Forbindelsesdatabasen er også mindre kritisk ifølge denne passage fra dokumentationen:"Det er ikke vigtigt, hvilken database du forbinder her, da scriptfilen oprettet af pg_dumpall vil indeholde de passende kommandoer til at oprette og oprette forbindelse til de gemte databaser."

Download Whitepaper Today PostgreSQL Management &Automation med ClusterControlFå flere oplysninger om, hvad du skal vide for at implementere, overvåge, administrere og skalere PostgreSQLDownload Whitepaper

pg_dump, pg_dumpall og shell-scripts - en praktisk kombination

I dette afsnit vil vi se et par eksempler på inkorporering af pg_dump og pg_dumpall i simple shell-scripts.

Vær klart, dette er ikke en shell script tutorial. Jeg er heller ikke en shell-script-guru. Jeg vil hovedsageligt give et par eksempler, jeg bruger i mit lokale udviklings-/læringsmiljø.

Lad os først se på et simpelt shell-script, du kan bruge til at sikkerhedskopiere en enkelt database:

#!/bin/bash
# This script performs a pg_dump, saving the file the specified dir.
# The first arg ($1) is the database user to connect with.
# The second arg ($2) is the database to backup and is included in the file name.
# $(date +"%Y_%m_%d") includes the current system date into the actual file name.

pg_dump -U $1 -W -C -d $2 > ~/PG_dumps/Dump_Scripts/$(date +"%Y_%m_%d")_$2.sql

Som du kan se, accepterer dette script 2 argumenter:det første er brugeren (eller rollen), der skal oprettes forbindelse til for sikkerhedskopieringen, mens det andet er navnet på den database, du vil sikkerhedskopiere.

Læg mærke til -C-indstillingen i kommandoen, så vi kan gendanne, hvis databasen tilfældigvis ikke eksisterer, uden at det er nødvendigt at oprette den manuelt på forhånd.

Lad os kalde scriptet med postgres-rollen for example_backups-databasen (Glem ikke at gøre scriptet eksekverbart med mindst chmod +x før du kalder for første gang):

$ ~/My_Scripts/pgd.sh postgres example_backups
Password:

Og bekræft, at den er der:

$ ls -a ~/PG_dumps/Dump_Scripts/
.  .. 2018_06_06_example_backups.sql

Gendannelse udføres med dette backupscript som i de foregående eksempler.

Et lignende shell-script kan bruges med pg_dumpall til at sikkerhedskopiere hele PostgreSQL-klyngen.

Dette shell-script sender (|) pg_dumpall ind i gzip, som derefter dirigeres til en udpeget filplacering:

#!/bin/bash
# This shell script calls pg_dumpall and pipes into the gzip utility, then directs to
# a directory for storage.
# $(date +"%Y_%m_%d") incorporates the current system date into the file name.
 
pg_dumpall -U postgres | gzip > ~/PG_dumps/Cluster_Dumps/$(date +"%Y_%m_%d")_pg_bck.gz

I modsætning til det forrige eksempelscript accepterer dette ikke nogen argumenter.

Jeg kalder dette script på kommandolinjen (ingen adgangskodeprompt, da postgres-rollen bruger ~/.pgpass-filen - Se afsnittet ovenfor.)

$ ~/My_Scripts/pgalldmp.sh

Når det er færdigt, vil jeg liste bibliotekets indhold, der også viser filstørrelser til sammenligning mellem .sql- og gz-filerne:

postgres=# \! ls -sh ~/PG_dumps/Cluster_Dumps
total 957M
37M 2018_05_22_pg_bck.gz   32M 2018_06_06_pg_bck.gz 445M entire_cluster2nd.sql  445M entire_cluster.sql

En note til gz-arkivformatet fra docs:

"De alternative arkivfilformater skal bruges med pg_restore for at genopbygge databasen."

Oversigt

Jeg har samlet nøglepunkter fra dokumentationen om pg_dump og pg_dumpall sammen med mine observationer for at lukke dette blogindlæg:

Bemærk:Punkter fra dokumentationen er i anførselstegn.

  • "pg_dump dumper kun en enkelt database"
  • SQL-filformatet med almindelig tekst er standardoutputtet for pg_dump.
  • En rolle har brug for SELECT-privilegiet for at køre pg_dump i henhold til denne linje i dokumentationen:"pg_dump udfører internt SELECT-sætninger. Hvis du har problemer med at køre pg_dump, så sørg for at du er i stand til at vælge information fra databasen ved hjælp af f.eks. psql”
  • For at inkludere den nødvendige DDL CREATE DATABASE-kommando og en forbindelse i backupfilen skal du inkludere -C-indstillingen.
  • -W:Denne mulighed tvinger pg_dump til at bede om en adgangskode. Dette flag er ikke nødvendigt, da hvis serveren kræver en adgangskode, bliver du alligevel bedt om det. Ikke desto mindre fangede denne passage i dokumentationen mit øje, så jeg tænkte at inkludere den her:"Pg_dump vil dog spilde et forbindelsesforsøg med at finde ud af, at serveren vil have en adgangskode. I nogle tilfælde er det værd at skrive -W for at undgå det ekstra forbindelsesforsøg.”
  • -d:Specificerer den database, der skal oprettes forbindelse til. Også i dokumentationen:"Dette svarer til at angive dbname som det første ikke-option-argument på kommandolinjen."
  • Anvendelse af flag såsom -t (tabel) giver brugerne mulighed for at sikkerhedskopiere dele af databasen, nemlig tabeller, de har adgangsrettigheder til.
  • Sikkerhedskopieringsfilformater kan variere. Men .sql-filer er et godt valg blandt andre. Sikkerhedskopier filer læses tilbage af psql for en gendannelse.
  • pg_dump kan sikkerhedskopiere en kørende, aktiv database uden at forstyrre andre operationer (dvs. andre læsere og skribenter).
  • Én advarsel:pg_dump dumper ikke roller eller andre databaseobjekter inklusive tablespaces, kun en enkelt database.
  • For at tage sikkerhedskopier af hele din PostgreSQL-klynge er pg_dumpall det bedre valg.
  • pg_dumpall kan håndtere hele klyngen, sikkerhedskopiere oplysninger om roller, tablespaces, brugere, tilladelser osv... hvor pg_dump ikke kan.
  • Der er chancer for, at en rolle med SUPERUSER-rettigheder skal udføre dumpet og gendanne/genskabe filen, når den læses tilbage gennem psql, fordi under gendannelse kræves privilegiet til at læse alle tabeller i alle databaser.

Mit håb er gennem dette blogindlæg, at jeg har givet tilstrækkelige eksempler og detaljer til en oversigt på begynderniveau på pg_dump og pg_dumpall for et enkelt udviklings-/lærings-PostgreSQL-miljø.

Selvom alle tilgængelige muligheder ikke blev undersøgt, indeholder den officielle dokumentation et væld af oplysninger med eksempler for begge hjælpeprogrammer, så sørg for at konsultere den ressource for yderligere undersøgelse, spørgsmål og læsning.


  1. MySQL - SELECT WHERE field IN (underforespørgsel) - Ekstremt langsom hvorfor?

  2. Fortsætter en transaktion efter fejl ved primærnøgleovertrædelse

  3. forskel mellem primær nøgle og unik nøgle

  4. PDO få det sidste ID indsat