Negócios e serviços entregam valor com base em dados. Disponibilidade, estado consistente e durabilidade são as principais prioridades para manter os clientes e usuários finais satisfeitos. Dados perdidos ou inacessíveis podem equivaler a clientes perdidos.
Os backups de banco de dados devem estar na vanguarda das operações e tarefas diárias.
Devemos estar preparados para o caso de nossos dados serem corrompidos ou perdidos.
Acredito firmemente em um velho ditado que ouvi:"É melhor ter e não precisar do que precisar e não ter . "
Isso também se aplica a backups de banco de dados. Vamos enfrentá-lo, sem eles, você basicamente não tem nada. Operar com a noção de que nada pode acontecer com seus dados é uma falácia.
A maioria dos SGBDs fornece alguns meios de utilitários de backup integrados. O PostgreSQL tem pg_dump e pg_dumpall prontos para uso.
Ambos apresentam inúmeras opções de personalização e estruturação. Cobrir todos eles individualmente em um post de blog seria quase impossível. Em vez disso, examinarei os exemplos que posso aplicar melhor ao meu ambiente de desenvolvimento/aprendizagem pessoal.
Dito isto, esta postagem de blog não é direcionada a um ambiente de produção. Mais provavelmente, uma única estação de trabalho/ambiente de desenvolvimento deve se beneficiar mais.
O que são pg_dump e pg_dumpall?
A documentação descreve o pg_dump como:“pg_dump é um utilitário para fazer backup de um banco de dados PostgreSQL”
E a documentação do pg_dumpall:“pg_dumpall é um utilitário para escrever (“dumping”) todos os bancos de dados PostgreSQL de um cluster em um arquivo de script.”
Fazendo backup de um banco de dados e/ou tabela(s)
Para começar, vou criar um banco de dados de prática e algumas tabelas para trabalhar usando o SQL abaixo:
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)
Banco de dados e tabelas todos configurados.
Anotar:
Em muitos desses exemplos, aproveitarei o \! do psql! meta-comando, permitindo que você entre em um shell (linha de comando) ou execute quaisquer comandos de shell que se seguem.
Apenas esteja ciente de que em um terminal ou sessão de linha de comando (indicado por um '$' inicial nesta postagem do blog), o \! meta-comando não deve ser incluído em nenhum dos comandos pg_dump ou pg_dumpall. Novamente, é um meta-comando de conveniência dentro do psql.
Fazendo backup de uma única tabela
Neste primeiro exemplo, vou despejar a única tabela de alunos:
example_backups=# \! pg_dump -U postgres -t students example_backups > ~/Example_Dumps/students.sql.
Listando o conteúdo do diretório, vemos que o arquivo está lá:
example_backups=# \! ls -a ~/Example_Dumps
. .. students.sql
As opções de linha de comando para este comando individual são:
- -U postgres:o nome de usuário especificado
- -t alunos:a tabela a ser despejada
- example_backups:o banco de dados
O que há no arquivo 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
Podemos ver que o arquivo possui os comandos SQL necessários para recriar e repovoar os alunos da tabela.
Mas, o backup é bom? Confiável e funcionando?
Vamos testar e ver.
example_backups=# DROP TABLE students;
DROP TABLE
example_backups=# \dt;
List of relations
Schema | Name | Type | Owner
--------+---------+-------+----------
public | classes | table | postgres
(1 row)
Foi-se.
Em seguida, na linha de comando, passe o backup salvo para o 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
Vamos verificar no banco de dados:
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)
A tabela e os dados foram restaurados.
Fazendo backup de várias tabelas
Neste próximo exemplo, faremos backup de ambas as tabelas usando este comando:
example_backups=# \! pg_dump -U postgres -W -t classes -t students -d example_backups > ~/Example_Dumps/all_tables.sql
Password:
(Observe que precisei especificar uma senha neste comando devido à opção -W, onde não fiz no primeiro exemplo. Mais sobre isso em breve.)
Vamos novamente verificar se o arquivo foi criado listando o conteúdo do diretório:
example_backups=# \! ls -a ~/Example_Dumps
. .. all_tables.sql students.sql
Em seguida, solte as tabelas:
example_backups=# DROP TABLE classes;
DROP TABLE
example_backups=# DROP TABLE students;
DROP TABLE
example_backups=# \dt;
Did not find any relations.
Em seguida, restaure com o arquivo de 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)
Ambas as tabelas foram restauradas.
Como podemos ver com o pg_dump, você pode fazer backup de apenas uma ou várias tabelas em um banco de dados específico.
Fazendo backup de um banco de dados
Vamos agora ver como fazer backup de todo o banco de dados example_backups com 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
O arquivo ex_back_db.sql está lá.
Vou me conectar ao banco de dados postgres para descartar o banco de dados example_backups.
postgres=# DROP DATABASE example_backups;
DROP DATABASE
Em seguida, restaure a partir da linha de 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
Não está lá. Por que não? E onde está?
Temos que criá-lo primeiro.
postgres=# CREATE DATABASE example_backups;
CREATE DATABASE
Em seguida, restaure com o mesmo 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)
Banco de dados e todas as tabelas presentes e contabilizadas.
Podemos evitar esse cenário de ter que criar o banco de dados de destino primeiro, incluindo a opção -C ao fazer o backup.
example_backups=# \! pg_dump -U postgres -W -C -d example_backups > ~/Example_Dumps/ex_back2_db.sql
Password:
Vou reconectar ao banco de dados postgres e descartar o banco de dados example_backups para que possamos ver como a restauração funciona agora (Observe os comandos connect e DROP não mostrados para brevidade).
Em seguida, na linha de comando (observe que não há opção -d dbname incluída):
$ 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
Usando a opção -C, é solicitada uma senha para fazer uma conexão, conforme mencionado na documentação referente ao sinalizador -C:
“Inicie a saída com um comando para criar o próprio banco de dados e se reconectar ao banco de dados criado.”
Em seguida, na sessão do psql:
postgres=# \c example_backups;
You are now connected to database "example_backups" as user "postgres".
Tudo é restaurado, pronto para uso e sem a necessidade de criar o banco de dados de destino antes da restauração.
pg_dumpall para todo o cluster
Até agora, fizemos backup de uma única tabela, várias tabelas e um único banco de dados.
Mas se quisermos mais do que isso, por exemplo, fazer backup de todo o cluster do PostgreSQL, é aí que precisamos usar o pg_dumpall.
Então, quais são algumas diferenças notáveis entre pg_dump e pg_dumpall?
Para começar, aqui está uma distinção importante da documentação:
“Como o pg_dumpall lê tabelas de todos os bancos de dados, você provavelmente terá que se conectar como um superusuário de banco de dados para produzir um dump completo. Além disso, você precisará de privilégios de superusuário para executar o script salvo para poder adicionar usuários e grupos e criar bancos de dados.”
Usando o comando abaixo, farei backup de todo o meu cluster PostgreSQL e o salvarei no arquivo 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:
O que na Terra? Você está se perguntando se eu tive que digitar uma senha para cada prompt?
Sim, com certeza. 24 vezes.
Conte-os. (Ei, eu gosto de explorar e me aprofundar em diferentes bancos de dados à medida que aprendo? O que posso dizer?)
Mas por que todos os prompts?
Em primeiro lugar, depois de todo esse trabalho duro, o pg_dumpall criou o arquivo de backup?
postgres=# \! ls -a ~/Example_Dumps/Cluster_Dumps
. .. entire_cluster.sql
Sim, o arquivo de backup está lá.
Vamos esclarecer um pouco sobre toda essa 'prática de digitação ' olhando para esta passagem da documentação:
“O pg_dumpall precisa se conectar várias vezes ao servidor PostgreSQL (uma vez por banco de dados). Se você usar autenticação de senha, ele solicitará uma senha a cada vez.”
Eu sei o que você está pensando.
Isso pode não ser ideal ou mesmo viável. E quanto a processos, scripts ou cron jobs que são executados no meio da noite?
Alguém vai passar o mouse sobre o teclado, esperando para digitar?
Provavelmente não.
Uma medida eficaz para evitar esses prompts de senha repetidos é um arquivo ~/.pgpass.
Aqui está a sintaxe que o arquivo ~/.pgpass requer para funcionar (exemplo fornecido na documentação, veja o link acima):
hostname:port:database:username:password
Com um arquivo ~/.pgpass presente em meu ambiente de desenvolvimento, contendo as credenciais necessárias para a função postgres, posso omitir a opção -W (também -w) e executar pg_dumpall sem autenticar manualmente com a senha:
$ pg_dumpall -U postgres -f ~/Example_Dumps/Cluster_Dumps/entire_cluster2nd.sql
Listando o conteúdo do diretório:
postgres=# \! ls -a ~/Example_Dumps/Cluster_Dumps
. .. entire_cluster2nd.sql entire_cluster.sql
O arquivo é criado e não há solicitações de senha repetidas.
O arquivo salvo pode ser recarregado com psql semelhante ao pg_dump.
O banco de dados de conexão também é menos crítico de acordo com esta passagem da documentação:“Não é importante para qual banco de dados você se conecta aqui, pois o arquivo de script criado por pg_dumpall conterá os comandos apropriados para criar e conectar-se aos bancos de dados salvos.”
Baixe o whitepaper hoje PostgreSQL Management &Automation with ClusterControlSaiba o que você precisa saber para implantar, monitorar, gerenciar e dimensionar o PostgreSQLBaixe o whitepaper
pg_dump, pg_dumpall e scripts de shell - uma combinação útil
Nesta seção, veremos alguns exemplos de incorporação de pg_dump e pg_dumpall em scripts de shell simples.
Para ser claro, este não é um tutorial de script de shell. Nem sou um guru de script de shell. Vou fornecer principalmente alguns exemplos que uso em meu ambiente local de desenvolvimento/aprendizagem.
Primeiro, vamos ver um script de shell simples que você pode usar para fazer backup de um único banco de dados:
#!/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
Como você pode ver, esse script aceita 2 argumentos:o primeiro é o usuário (ou função) com o qual se conectar para o backup, enquanto o segundo é o nome do banco de dados que você deseja fazer backup.
Observe a opção -C no comando para que possamos restaurar se o banco de dados não existir, sem a necessidade de criá-lo manualmente antes.
Vamos chamar o script com a função postgres para o banco de dados example_backups (não se esqueça de tornar o script executável com pelo menos chmod +x antes de chamar pela primeira vez):
$ ~/My_Scripts/pgd.sh postgres example_backups
Password:
E verifique se está lá:
$ ls -a ~/PG_dumps/Dump_Scripts/
. .. 2018_06_06_example_backups.sql
A restauração é executada com este script de backup como nos exemplos anteriores.
Um shell script semelhante pode ser usado com pg_dumpall para fazer backup de todo o cluster PostgreSQL.
Este script de shell enviará (|) pg_dumpall para o gzip, que será direcionado para um local de arquivo designado:
#!/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
Ao contrário do script de exemplo anterior, este não aceita nenhum argumento.
Vou chamar esse script na linha de comando (sem prompt de senha, pois a função postgres utiliza o arquivo ~/.pgpass - Consulte a seção acima.)
$ ~/My_Scripts/pgalldmp.sh
Depois de concluído, listarei o conteúdo do diretório também mostrando os tamanhos dos arquivos para comparação entre os arquivos .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
Uma nota para o formato de arquivo gz dos documentos:
“Os formatos alternativos de arquivo devem ser usados com pg_restore para reconstruir o banco de dados.”
Resumo
Reuni pontos-chave da documentação em pg_dump e pg_dumpall, juntamente com minhas observações, para encerrar esta postagem no blog:
Nota:Os pontos fornecidos na documentação estão entre aspas.
- “pg_dump apenas despeja um único banco de dados”
- O formato de arquivo SQL de texto simples é a saída padrão para pg_dump.
- Uma função precisa do privilégio SELECT para executar o pg_dump de acordo com esta linha na documentação:“pg_dump executa internamente instruções SELECT. Se você tiver problemas ao executar o pg_dump, certifique-se de poder selecionar informações do banco de dados usando, por exemplo, psql”
- Para incluir o comando DDL CREATE DATABASE necessário e uma conexão no arquivo de backup, inclua a opção -C.
- -W:Esta opção força o pg_dump a solicitar uma senha. Esse sinalizador não é necessário, pois se o servidor exigir uma senha, você será solicitado de qualquer maneira. No entanto, esta passagem na documentação chamou minha atenção, então pensei em incluí-la aqui:“No entanto, o pg_dump desperdiçará uma tentativa de conexão descobrindo que o servidor deseja uma senha. Em alguns casos vale a pena digitar -W para evitar a tentativa de conexão extra.”
- -d:especifica o banco de dados ao qual se conectar. Também na documentação:”Isso é equivalente a especificar dbname como o primeiro argumento não opcional na linha de comando.”
- A utilização de sinalizadores como -t (tabela) permite que os usuários façam backup de partes do banco de dados, ou seja, tabelas, para as quais eles têm privilégios de acesso.
- Os formatos de arquivo de backup podem variar. No entanto, os arquivos .sql são uma ótima opção entre outros. Os arquivos de backup são lidos pelo psql para uma restauração.
- pg_dump pode fazer backup de um banco de dados ativo em execução sem interferir em outras operações (ou seja, outros leitores e gravadores).
- Uma ressalva:o pg_dump não despeja funções ou outros objetos de banco de dados, incluindo tablespaces, apenas um único banco de dados.
- Para fazer backups de todo o cluster do PostgreSQL, pg_dumpall é a melhor escolha.
- pg_dumpall pode lidar com todo o cluster, fazendo backup de informações sobre funções, tablespaces, usuários, permissões, etc... onde o pg_dump não pode.
- Provavelmente, uma função com privilégios de SUPERUSER terá que executar o dump e restaurar/recriar o arquivo quando ele for lido de volta através do psql porque durante a restauração, o privilégio de ler todas as tabelas em todos os bancos de dados é necessário. l>
Minha esperança é que, por meio desta postagem no blog, forneça exemplos e detalhes adequados para uma visão geral de nível iniciante em pg_dump e pg_dumpall para um único ambiente PostgreSQL de desenvolvimento/aprendizagem.
Embora todas as opções disponíveis não tenham sido exploradas, a documentação oficial contém uma riqueza de informações com exemplos para ambos os utilitários, portanto, certifique-se e consulte esse recurso para estudos adicionais, perguntas e leitura.