sql >> Databasteknik >  >> RDS >> PostgreSQL

Säkerhetskopiera PostgreSQL med pg_dump och pg_dumpall

Företag och tjänster levererar värde baserat på data. Tillgänglighet, konsekvent tillstånd och hållbarhet är högsta prioritet för att hålla kunder och slutanvändare nöjda. Förlorad eller otillgänglig data kan möjligen likställas med förlorade kunder.

Databassäkerhetskopior bör ligga i framkant i den dagliga verksamheten och uppgifterna.

Vi bör vara förberedda på händelsen att vår data blir skadad eller förlorad.

Jag tror starkt på ett gammalt talesätt jag har hört:"Det är bättre att ha det och inte behöva det än att behöva det och inte ha det . "

Det gäller även säkerhetskopiering av databas. Låt oss inse det, utan dem har du i princip ingenting. Att arbeta utifrån föreställningen att ingenting kan hända med din data är en felaktighet.

De flesta DBMS tillhandahåller vissa medel för inbyggda säkerhetskopieringsverktyg. PostgreSQL har pg_dump och pg_dumpall ur kartongen.

Båda presenterar många anpassnings- och struktureringsmöjligheter. Att täcka dem alla individuellt i ett blogginlägg skulle vara näst intill omöjligt. Istället ska jag titta på de exempel jag kan tillämpa bäst på min personliga utveckling/inlärningsmiljö.

Med det sagt är det här blogginlägget inte riktat till en produktionsmiljö. Mer troligt är att en enskild arbetsstation/utvecklingsmiljö borde gynnas mest.

Vad är pg_dump och pg_dumpall?

Dokumentationen beskriver pg_dump som:"pg_dump är ett verktyg för att säkerhetskopiera en PostgreSQL-databas"

Och pg_dumpall-dokumentationen:"pg_dumpall är ett verktyg för att skriva ut ("dumpa") alla PostgreSQL-databaser i ett kluster till en skriptfil."

Säkerhetskopiera en databas och/eller tabell(er)

Till att börja med skapar jag en övningsdatabas och några tabeller att arbeta med med hjälp av nedanstå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)

Databas och tabeller är alla inställda.

Att notera:

I många av dessa exempel kommer jag att dra fördel av psqls \! meta-kommando, som låter dig antingen släppa in i ett skal (kommandorad) eller utföra de skalkommandon som följer.

Tänk bara på att i en terminal- eller kommandoradssession (betecknad med en ledande '$' i det här blogginlägget), är \! meta-kommando ska inte inkluderas i något av kommandona pg_dump eller pg_dumpall. Återigen, det är ett bekvämlighets-metakommando inom psql.

Säkerhetskopiera en enskild tabell

I det här första exemplet dumpar jag den enda elevtabellen:

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

När vi listar katalogens innehåll ser vi att filen finns där:

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

Kommandoradsalternativen för detta individuella kommando är:

  • -U postgres:det angivna användarnamnet
  • -t studenter:tabellen att dumpa
  • example_backups:databasen

Vad finns 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 att filen har de nödvändiga SQL-kommandona för att återskapa och fylla i tabellstudenter.

Men är backupen bra? Pålitlig och fungerande?

Vi kommer att testa det och 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 är borta.

Skicka sedan den sparade säkerhetskopian till psql:

från kommandoraden
$ 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

Låt oss verifiera 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)

Tabell och data har återställts.

Säkerhetskopiera flera tabeller

I nästa exempel kommer vi att säkerhetskopiera båda tabellerna med detta kommando:

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

(Observera att jag behövde ange ett lösenord i det här kommandot på grund av alternativet -W, ​​där jag inte gjorde det i det första exemplet. Mer om detta kommer.)

Låt oss återigen verifiera att filen skapades genom att lista ut kataloginnehållet:

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

Släpp sedan tabellerna:

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

Återställ sedan 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)

Båda tabellerna har återställts.

Som vi kan se med pg_dump kan du bara säkerhetskopiera en eller flera tabeller i en specifik databas.

Säkerhetskopiera en databas

Låt oss nu se hur man säkerhetskopierar hela databasen example_backups 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

Filen ex_back_db.sql finns där.

Jag kommer att ansluta till postgres-databasen för att ta bort databasen example_backups.

postgres=# DROP DATABASE example_backups;
DROP DATABASE

Återställ sedan från kommandoraden:

$ 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

Den är inte där. Varför inte? Och var är det?

Vi måste skapa den först.

postgres=# CREATE DATABASE example_backups;
CREATE DATABASE

Återställ sedan med samma 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)

Databas och alla tabeller som finns och redovisas.

Vi kan undvika detta scenario med att behöva skapa måldatabasen först, genom att inkludera alternativet -C när du tar säkerhetskopian.

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

Jag återansluter till postgres-databasen och släpper databasen example_backups så att vi kan se hur återställningen fungerar nu (Observera att connect- och DROP-kommandona inte visas för korthetens skull).

Sedan på kommandoraden (notera att inget -d dbname-alternativ ingår):

$ 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

Med alternativet -C uppmanas vi att ange ett lösenord för att göra en anslutning som nämns i dokumentationen om flaggan -C:

"Börja utdata med ett kommando för att skapa själva databasen och återanslut till den skapade databasen."

Sedan i psql-sessionen:

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

Allt är återställt, bra att köra och utan att du behöver skapa måldatabasen före återställningen.

pg_dumpall för hela klustret

Hittills har vi säkerhetskopierat en enda tabell, flera tabeller och en enda databas.

Men om vi vill ha mer än så, till exempel att säkerhetskopiera hela PostgreSQL-klustret, är det där vi måste använda pg_dumpall.

Så vad är några anmärkningsvärda skillnader mellan pg_dump och pg_dumpall?

Till att börja med, här är en viktig skillnad från dokumentationen:

"Eftersom pg_dumpall läser tabeller från alla databaser, kommer du med största sannolikhet att behöva ansluta som en databassuperanvändare för att skapa en komplett dump. Du kommer också att behöva superanvändarprivilegier för att köra det sparade skriptet för att tillåtas lägga till användare och grupper och skapa databaser.”

Med kommandot nedan kommer jag att säkerhetskopiera hela mitt PostgreSQL-kluster och spara det 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:

Vad i hela friden? Undrar du om jag var tvungen att ange ett lösenord för varje prompt?

Japp, visst gjorde det. 24 gånger.

Räkna dem. (Hej, jag gillar att utforska och fördjupa mig i olika databaser när jag lär mig? Vad kan jag säga?)

Men varför alla uppmaningar?

Först av allt, efter allt det hårda arbetet, skapade pg_dumpall säkerhetskopian?

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

Japp, säkerhetskopian finns där.

Låt oss kasta lite ljus över all den där "skrivövningen genom att titta på det här avsnittet från dokumentationen:

“pg_dumpall behöver ansluta flera gånger till PostgreSQL-servern (en gång per databas). Om du använder lösenordsautentisering kommer den att be om ett lösenord varje gång.”

Jag vet vad du tänker.

Detta kanske inte är idealiskt eller ens genomförbart. Hur är det med processer, skript eller cron-jobb som körs mitt i natten?

Kommer någon att hålla muspekaren över tangentbordet och vänta på att skriva?

Förmodligen inte.

En effektiv åtgärd för att förhindra att du möter de upprepade lösenordsuppmaningarna är en ~/.pgpass-fil.

Här är syntaxen som ~/.pgpass-filen kräver för att fungera (exempel från dokumentationen, se länken ovan):

hostname:port:database:username:password

Med en ~/.pgpass-fil i min utvecklingsmiljö, som innehåller de nödvändiga referenserna för postgres-rollen, kan jag utelämna alternativet -W (även -w) och köra pg_dumpall utan att manuellt autentisera med lösenordet:

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

Lista ut katalogens innehåll:

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

Filen skapas och inga upprepade lösenord uppmanas.

Den sparade filen kan laddas om med psql liknande pg_dump.

Anslutningsdatabasen är också mindre kritisk enligt denna passage från dokumentationen:"Det är inte viktigt till vilken databas du ansluter här eftersom skriptfilen skapad av pg_dumpall kommer att innehålla lämpliga kommandon för att skapa och ansluta till de sparade databaserna."

Ladda ner Whitepaper Today PostgreSQL Management &Automation med ClusterControlLäs om vad du behöver veta för att distribuera, övervaka, hantera och skala PostgreSQLDladda Whitepaper

pg_dump-, pg_dumpall- och skalskript – en praktisk kombination

I det här avsnittet kommer vi att se ett par exempel på hur pg_dump och pg_dumpall integreras i enkla skalskript.

Var tydlig, detta är inte en skalskripthandledning. Jag är inte heller en skalskriptguru. Jag kommer främst att ge ett par exempel som jag använder i min lokala utvecklings-/inlärningsmiljö.

Låt oss först titta på ett enkelt skalskript som du kan använda för att säkerhetskopiera en enda databas:

#!/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 accepterar det här skriptet 2 argument:det första är användaren (eller rollen) att ansluta till för säkerhetskopieringen, medan det andra är namnet på databasen du vill säkerhetskopiera.

Lägg märke till alternativet -C i kommandot så att vi kan återställa om databasen råkar vara obefintlig, utan att behöva skapa den manuellt i förväg.

Låt oss kalla skriptet med postgres-rollen för databasen example_backups (Glöm inte att göra skriptet körbart med minst chmod +x innan du anropar för första gången):

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

Och verifiera att den finns där:

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

Återställning utförs med detta säkerhetskopieringsskript som i de tidigare exemplen.

Ett liknande skalskript kan användas med pg_dumpall för att säkerhetskopiera hela PostgreSQL-klustret.

Det här skalskriptet skickar (|) pg_dumpall till gzip, som sedan dirigeras till en angiven filplats:

#!/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

Till skillnad från föregående exempelskript accepterar inte detta några argument.

Jag kallar det här skriptet på kommandoraden (ingen lösenordsuppmaning eftersom postgres-rollen använder ~/.pgpass-filen - Se avsnittet ovan.)

$ ~/My_Scripts/pgalldmp.sh

När det är klart kommer jag att lista kataloginnehållet och även visa filstorlekar för jämförelse mellan .sql- och gz-filerna:

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 notering för gz-arkivformatet från dokumenten:

"De alternativa arkivfilformaten måste användas med pg_restore för att bygga om databasen."

Sammanfattning

Jag har samlat nyckelpunkter från dokumentationen om pg_dump och pg_dumpall, tillsammans med mina observationer, för att avsluta detta blogginlägg:

Notera:Punkter från dokumentationen är inom citattecken.

  • "pg_dump dumpar bara en enda databas"
  • SQL-filformatet med oformaterad text är standardutdata för pg_dump.
  • En roll behöver SELECT-behörigheten för att köra pg_dump enligt denna rad i dokumentationen:"pg_dump exekverar internt SELECT-satser. Om du har problem med att köra pg_dump, se till att du kan välja information från databasen med till exempel psql”
  • För att inkludera det nödvändiga DDL CREATE DATABASE-kommandot och en anslutning i säkerhetskopian, inkludera alternativet -C.
  • -W:Detta alternativ tvingar pg_dump att fråga efter ett lösenord. Denna flagga är inte nödvändig eftersom om servern kräver ett lösenord, tillfrågas du ändå. Ändå fångade det här stycket i dokumentationen mitt öga så jag tänkte inkludera det här:"Men pg_dump kommer att slösa bort ett anslutningsförsök på att ta reda på att servern vill ha ett lösenord. I vissa fall är det värt att skriva -W för att undvika det extra anslutningsförsöket.”
  • -d:Anger databasen som ska anslutas till. Även i dokumentationen:"Detta motsvarar att ange dbname som det första icke-alternativargumentet på kommandoraden."
  • Genom att använda flaggor som -t (tabell) kan användare säkerhetskopiera delar av databasen, nämligen tabeller, som de har åtkomstbehörighet för.
  • Säkerhetskopieringsfilformat kan variera. Men .sql-filer är ett utmärkt val bland andra. Säkerhetskopierade filer läses in igen av psql för en återställning.
  • pg_dump kan säkerhetskopiera en pågående, aktiv databas utan att störa andra operationer (d.v.s. andra läsare och skribenter).
  • En varning:pg_dump dumpar inte roller eller andra databasobjekt inklusive tabellutrymmen, bara en enda databas.
  • För att ta säkerhetskopior av hela ditt PostgreSQL-kluster är pg_dumpall det bättre valet.
  • pg_dumpall kan hantera hela klustret, säkerhetskopiera information om roller, tabellutrymmen, användare, behörigheter, etc... där pg_dump inte kan.
  • Möjligen måste en roll med SUPERUSER-behörighet utföra dumpningen och återställa/återskapa filen när den läses in via psql eftersom det krävs behörighet att läsa alla tabeller i alla databaser under återställning.

Min förhoppning är att genom det här blogginlägget har jag tillhandahållit adekvata exempel och detaljer för en översikt på nybörjarnivå på pg_dump och pg_dumpall för en enda utvecklings-/lärande PostgreSQL-miljöer.

Även om alla tillgängliga alternativ inte undersöktes, innehåller den officiella dokumentationen en mängd information med exempel för båda verktygen, så var säker och konsultera den resursen för ytterligare studier, frågor och läsning.


  1. hur du gör din data horisontell

  2. Hur man importerar CSV-fil i PostgreSQL

  3. Var lagrar Android SQLites databasversion?

  4. Returnera en lista över databaser i SQLite