Le aziende e i servizi forniscono valore basato sui dati. Disponibilità, stato coerente e durabilità sono le massime priorità per mantenere i clienti e gli utenti finali soddisfatti. I dati persi o inaccessibili potrebbero essere sinonimo di perdita di clienti.
I backup del database dovrebbero essere in prima linea nelle operazioni e nelle attività quotidiane.
Dovremmo essere preparati all'eventualità che i nostri dati vengano danneggiati o persi.
Credo fermamente in un vecchio detto che ho sentito dire:"È meglio averlo e non averne bisogno che averne bisogno e non averlo . "
Questo vale anche per i backup del database. Ammettiamolo, senza di loro non hai praticamente nulla. Operare sulla base dell'idea che nulla può accadere ai tuoi dati è un errore.
La maggior parte dei DBMS fornisce alcuni mezzi di utilità di backup integrate. PostgreSQL ha pg_dump e pg_dumpall pronti all'uso.
Entrambi presentano numerose opzioni di personalizzazione e strutturazione. Coprirli tutti individualmente in un post sul blog sarebbe quasi impossibile. Invece, guarderò quegli esempi che posso applicare meglio, al mio ambiente di sviluppo/apprendimento personale.
Detto questo, questo post del blog non è destinato a un ambiente di produzione. Più probabilmente, una singola workstation/ambiente di sviluppo dovrebbe trarre il massimo vantaggio.
Cosa sono pg_dump e pg_dumpall?
La documentazione descrive pg_dump come:“pg_dump è un'utilità per il backup di un database PostgreSQL”
E la documentazione di pg_dumpall:"pg_dumpall è un'utilità per scrivere ("dumping") tutti i database PostgreSQL di un cluster in un unico file di script."
Backup di un database e/o tabelle
Per iniziare, creerò un database pratico e alcune tabelle con cui lavorare utilizzando l'SQL seguente:
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 e tabelle tutti impostati.
Da notare:
In molti di questi esempi, trarrò vantaggio da \! di psql meta-comando, che ti consente di entrare in una shell (riga di comando) o di eseguire qualsiasi comando di shell che segue.
Tieni solo presente che in una sessione del terminale o della riga di comando (indicata da un "$" iniziale in questo post del blog), \! il meta-comando non dovrebbe essere incluso in nessuno dei comandi pg_dump o pg_dumpall. Ancora una volta, è un comodo meta-comando all'interno di psql.
Backup di una singola tabella
In questo primo esempio, eliminerò l'unica tabella studenti:
example_backups=# \! pg_dump -U postgres -t students example_backups > ~/Example_Dumps/students.sql.
Elencando il contenuto della directory, vediamo che il file è lì:
example_backups=# \! ls -a ~/Example_Dumps
. .. students.sql
Le opzioni della riga di comando per questo singolo comando sono:
- -U postgres:il nome utente specificato
- -t studenti:il tavolo da scaricare
- backup_esempio:il database
Cosa c'è nel file Students.sql?
$ 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
Possiamo vedere che il file ha i comandi SQL necessari per ricreare e ripopolare gli studenti della tabella.
Ma il backup è buono? Affidabile e funzionante?
Lo proveremo e vedremo.
example_backups=# DROP TABLE students;
DROP TABLE
example_backups=# \dt;
List of relations
Schema | Name | Type | Owner
--------+---------+-------+----------
public | classes | table | postgres
(1 row)
Non c'è più.
Quindi dalla riga di comando passa il backup salvato in 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
Verifichiamo nel database:
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)
Tabella e dati sono stati ripristinati.
Backup di più tabelle
In questo prossimo esempio, eseguiremo il backup di entrambe le tabelle usando questo comando:
example_backups=# \! pg_dump -U postgres -W -t classes -t students -d example_backups > ~/Example_Dumps/all_tables.sql
Password:
(Nota che dovevo specificare una password in questo comando a causa dell'opzione -W, dove non l'avevo fatto nel primo esempio. Maggiori informazioni su questo a venire.)
Verifichiamo ancora una volta che il file sia stato creato elencando il contenuto della directory:
example_backups=# \! ls -a ~/Example_Dumps
. .. all_tables.sql students.sql
Quindi rilascia le tabelle:
example_backups=# DROP TABLE classes;
DROP TABLE
example_backups=# DROP TABLE students;
DROP TABLE
example_backups=# \dt;
Did not find any relations.
Quindi ripristina con il file di backup 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)
Entrambe le tabelle sono state ripristinate.
Come possiamo vedere con pg_dump, puoi eseguire il backup di una o più tabelle all'interno di un database specifico.
Backup di un database
Vediamo ora come eseguire il backup dell'intero database example_backups con 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
Il file ex_back_db.sql è lì.
Mi collegherò al database postgres per eliminare il database example_backups.
postgres=# DROP DATABASE example_backups;
DROP DATABASE
Quindi ripristina dalla riga di comando:
$ 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
Non è lì. Perchè no? E dov'è?
Dobbiamo prima crearlo.
postgres=# CREATE DATABASE example_backups;
CREATE DATABASE
Quindi ripristina con lo stesso comando:
$ 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 e tutte le tabelle presenti e contabilizzate.
Possiamo evitare questo scenario di dover creare prima il database di destinazione, includendo l'opzione -C durante l'esecuzione del backup.
example_backups=# \! pg_dump -U postgres -W -C -d example_backups > ~/Example_Dumps/ex_back2_db.sql
Password:
Mi ricollegherò al database postgres ed eliminerò il database example_backups in modo da poter vedere come funziona il ripristino ora (nota quei comandi connect e DROP non mostrati per brevità).
Quindi sulla riga di comando (notare che non è inclusa l'opzione -d dbname):
$ 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
Utilizzando l'opzione -C, ci viene richiesta una password per effettuare una connessione come menzionato nella documentazione relativa al flag -C:
"Inizia l'output con un comando per creare il database stesso e riconnetterti al database creato."
Quindi nella sessione psql:
postgres=# \c example_backups;
You are now connected to database "example_backups" as user "postgres".
Tutto è ripristinato, pronto per l'uso e senza la necessità di creare il database di destinazione prima del ripristino.
pg_dumpall per l'intero cluster
Finora, abbiamo eseguito il backup di una singola tabella, più tabelle e un singolo database.
Ma se vogliamo di più, ad esempio il backup dell'intero cluster PostgreSQL, è lì che dobbiamo usare pg_dumpall.
Quindi quali sono alcune differenze notevoli tra pg_dump e pg_dumpall?
Per cominciare, ecco un'importante distinzione dalla documentazione:
“Dato che pg_dumpall legge le tabelle da tutti i database, molto probabilmente dovrai connetterti come superutente del database per produrre un dump completo. Inoltre, avrai bisogno dei privilegi di superutente per eseguire lo script salvato in modo da poter aggiungere utenti e gruppi e creare database."
Usando il comando seguente, eseguirò il backup dell'intero cluster PostgreSQL e lo salverò nel file 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:
Cosa diavolo? Ti stai chiedendo se dovevo inserire una password per ogni richiesta?
Sì, certo. 24 volte.
Contali. (Ehi, mi piace esplorare e approfondire diversi database mentre imparo? Cosa posso dire?)
Ma perché tutte le richieste?
Prima di tutto, dopo tutto quel duro lavoro, pg_dumpall ha creato il file di backup?
postgres=# \! ls -a ~/Example_Dumps/Cluster_Dumps
. .. entire_cluster.sql
Sì, il file di backup è lì.
Facciamo un po' di luce su tutta quella "pratica di digitazione". ' guardando questo passaggio della documentazione:
“pg_dumpall deve connettersi più volte al server PostgreSQL (una volta per database). Se utilizzi l'autenticazione tramite password, ti verrà richiesta una password ogni volta."
So cosa stai pensando.
Questo potrebbe non essere l'ideale o addirittura fattibile. Che dire di processi, script o processi cron eseguiti nel cuore della notte?
Qualcuno passerà con il mouse sopra la tastiera, in attesa di digitare?
Probabilmente no.
Una misura efficace per evitare di dover affrontare le ripetute richieste di password è un file ~/.pgpass.
Ecco la sintassi che il file ~/.pgpass richiede per funzionare (esempio fornito dalla documentazione vedi link sopra):
hostname:port:database:username:password
Con un file ~/.pgpass presente nel mio ambiente di sviluppo, contenente le credenziali necessarie per il ruolo postgres, posso omettere l'opzione -W (anche -w) ed eseguire pg_dumpall senza autenticarmi manualmente con la password:
$ pg_dumpall -U postgres -f ~/Example_Dumps/Cluster_Dumps/entire_cluster2nd.sql
Elencare il contenuto della directory:
postgres=# \! ls -a ~/Example_Dumps/Cluster_Dumps
. .. entire_cluster2nd.sql entire_cluster.sql
Il file viene creato e nessuna richiesta di password ripetuta.
Il file salvato può essere ricaricato con psql simile a pg_dump.
Anche il database di connessione è meno critico secondo questo passaggio della documentazione:”Non è importante a quale database ci si collega qui poiché il file di script creato da pg_dumpall conterrà i comandi appropriati per creare e connettersi ai database salvati.”
Scarica il whitepaper oggi Gestione e automazione di PostgreSQL con ClusterControlScopri cosa devi sapere per distribuire, monitorare, gestire e ridimensionare PostgreSQLScarica il whitepaperScript pg_dump, pg_dumpall e shell:una pratica combinazione
In questa sezione vedremo un paio di esempi di incorporazione di pg_dump e pg_dumpall in semplici script di shell.
Sia chiaro, questo non è un tutorial di script di shell. Né sono un guru degli script di shell. Fornirò principalmente un paio di esempi che utilizzo nel mio ambiente di sviluppo/apprendimento locale.
Per prima cosa, diamo un'occhiata a un semplice script di shell che puoi utilizzare per eseguire il backup di un singolo 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
Come puoi vedere, questo script accetta 2 argomenti:il primo è l'utente (o il ruolo) con cui connettersi per il backup, mentre il secondo è il nome del database di cui vuoi eseguire il backup.
Notare l'opzione -C nel comando in modo da poter ripristinare se il database risulta inesistente, senza la necessità di crearlo manualmente in anticipo.
Chiamiamo lo script con il ruolo postgres per il database example_backups (non dimenticare di rendere eseguibile lo script con almeno chmod +x prima di chiamare per la prima volta):
$ ~/My_Scripts/pgd.sh postgres example_backups
Password:
E verifica che sia lì:
$ ls -a ~/PG_dumps/Dump_Scripts/
. .. 2018_06_06_example_backups.sql
Il ripristino viene eseguito con questo script di backup come negli esempi precedenti.
Uno script di shell simile può essere utilizzato con pg_dumpall per il backup dell'intero cluster PostgreSQL.
Questo script di shell convoglierà (|) pg_dumpall in gzip, che viene quindi indirizzato a un percorso di file designato:
#!/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
A differenza del precedente script di esempio, questo non accetta argomenti.
Chiamerò questo script sulla riga di comando (nessuna richiesta di password poiché il ruolo postgres utilizza il file ~/.pgpass - Vedi la sezione sopra.)
$ ~/My_Scripts/pgalldmp.sh
Una volta completato, elencherò il contenuto della directory mostrando anche le dimensioni dei file per il confronto tra i file .sql e gz:
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
Una nota per il formato di archivio gz dai documenti:
"I formati di file di archivio alternativi devono essere utilizzati con pg_restore per ricostruire il database."
Riepilogo
Ho raccolto i punti chiave della documentazione su pg_dump e pg_dumpall, insieme alle mie osservazioni, per chiudere questo post del blog:
Nota:i punti forniti dalla documentazione sono tra virgolette.
- "pg_dump esegue il dump solo di un singolo database"
- Il formato del file SQL in testo semplice è l'output predefinito per pg_dump.
- Un ruolo necessita del privilegio SELECT per eseguire pg_dump secondo questa riga nella documentazione:“pg_dump esegue internamente le istruzioni SELECT. Se hai problemi con l'esecuzione di pg_dump, assicurati di poter selezionare le informazioni dal database usando, ad esempio, psql”
- Per includere il comando DDL CREATE DATABASE necessario e una connessione nel file di backup, includi l'opzione -C.
- -W:questa opzione forza pg_dump a richiedere una password. Questo flag non è necessario poiché se il server richiede una password, ti viene comunque richiesta. Tuttavia, questo passaggio nella documentazione ha attirato la mia attenzione, quindi ho pensato di includerlo qui:“Tuttavia, pg_dump sprecherà un tentativo di connessione scoprendo che il server vuole una password. In alcuni casi vale la pena digitare -W per evitare il tentativo di connessione extra."
- -d:specifica il database a cui connettersi. Anche nella documentazione:”Questo equivale a specificare dbname come primo argomento non-opzione sulla riga di comando.”
- L'utilizzo di flag come -t (tabella) consente agli utenti di eseguire il backup di porzioni del database, in particolare le tabelle, per le quali dispongono dei privilegi di accesso.
- I formati dei file di backup possono variare. Tuttavia, i file .sql sono un'ottima scelta tra gli altri. I file di backup vengono riletti da psql per un ripristino.
- pg_dump può eseguire il backup di un database attivo e in esecuzione senza interferire con altre operazioni (ad esempio, altri lettori e autori).
- Un avvertimento:pg_dump non esegue il dump dei ruoli o di altri oggetti del database, inclusi i tablespace, ma solo un singolo database.
- Per eseguire backup sull'intero cluster PostgreSQL, pg_dumpall è la scelta migliore.
- pg_dumpall può gestire l'intero cluster, eseguendo il backup delle informazioni su ruoli, tablespace, utenti, autorizzazioni, ecc... dove pg_dump non può.
- È probabile che un ruolo con privilegi SUPERUSER dovrà eseguire il dump e ripristinare/ricreare il file quando viene riletto tramite psql perché durante il ripristino è richiesto il privilegio di leggere tutte le tabelle in tutti i database.
La mia speranza è che attraverso questo post sul blog ho fornito esempi e dettagli adeguati per una panoramica di livello principiante su pg_dump e pg_dumpall per un singolo ambiente di sviluppo/apprendimento PostgreSQL.
Sebbene tutte le opzioni disponibili non siano state esplorate, la documentazione ufficiale contiene una grande quantità di informazioni con esempi per entrambe le utility, quindi assicurati di consultare quella risorsa per ulteriori studi, domande e letture.