sql >> Base de Datos >  >> RDS >> PostgreSQL

Copia de seguridad de PostgreSQL usando pg_dump y pg_dumpall

Las empresas y los servicios ofrecen valor en función de los datos. La disponibilidad, el estado consistente y la durabilidad son las principales prioridades para mantener satisfechos a los clientes y usuarios finales. Los datos perdidos o inaccesibles posiblemente podrían equivaler a la pérdida de clientes.

Las copias de seguridad de la base de datos deben estar a la vanguardia de las operaciones y tareas diarias.

Debemos estar preparados para el caso de que nuestros datos se dañen o se pierdan.

Creo firmemente en un viejo dicho que he escuchado:"Es mejor tenerlo y no necesitarlo que necesitarlo y no tenerlo . "

Eso también se aplica a las copias de seguridad de la base de datos. Seamos realistas, sin ellos, básicamente no tienes nada. Operar con la idea de que nada puede pasarle a sus datos es una falacia.

La mayoría de los DBMS proporcionan algún medio de utilidades de copia de seguridad integradas. PostgreSQL tiene pg_dump y pg_dumpall listos para usar.

Ambos presentan numerosas opciones de personalización y estructuración. Cubrirlos a todos individualmente en una publicación de blog sería casi imposible. En su lugar, veré los ejemplos que puedo aplicar mejor a mi entorno de desarrollo/aprendizaje personal.

Dicho esto, esta publicación de blog no está dirigida a un entorno de producción. Lo más probable es que una única estación de trabajo/entorno de desarrollo sea la que más se beneficie.

¿Qué son pg_dump y pg_dumpall?

La documentación describe pg_dump como:"pg_dump es una utilidad para realizar copias de seguridad de una base de datos PostgreSQL"

Y la documentación de pg_dumpall:"pg_dumpall es una utilidad para escribir ("descargar") todas las bases de datos PostgreSQL de un clúster en un archivo de script".

Copia de seguridad de una base de datos y/o tabla(s)

Para comenzar, crearé una base de datos de práctica y algunas tablas para trabajar usando el siguiente 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)

Base de datos y tablas configuradas.

A tener en cuenta:

En muchos de estos ejemplos, aprovecharé el \! de psql. metacomando, que le permite ingresar a un shell (línea de comandos) o ejecutar los comandos de shell que siguen.

Solo tenga en cuenta que en una sesión de terminal o de línea de comandos (indicada por un '$' inicial en esta publicación de blog), el \! El metacomando no debe incluirse en ninguno de los comandos pg_dump o pg_dumpall. Una vez más, es un metacomando conveniente dentro de psql.

Copia de seguridad de una sola tabla

En este primer ejemplo, volcaré solo la tabla de estudiantes:

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

Al enumerar el contenido del directorio, vemos que el archivo está allí:

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

Las opciones de la línea de comandos para este comando individual son:

  • -U postgres:el nombre de usuario especificado
  • -t estudiantes:la mesa para volcar
  • example_backups:la base de datos

¿Qué hay en el archivo 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 el archivo tiene los comandos SQL necesarios para volver a crear y volver a llenar la tabla de estudiantes.

Pero, ¿la copia de seguridad es buena? ¿Confiable y funcionando?

Lo probaremos y veremos.

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

Se ha ido.

Luego, desde la línea de comandos, pase la copia de seguridad guardada a 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

Verifiquemos en la base de datos:

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)

La tabla y los datos han sido restaurados.

Copia de seguridad de varias tablas

En el siguiente ejemplo, haremos una copia de seguridad de ambas tablas usando este comando:

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

(Tenga en cuenta que necesitaba especificar una contraseña en este comando debido a la opción -W, donde no lo hice en el primer ejemplo. Más sobre esto por venir).

Verifiquemos nuevamente que el archivo se creó enumerando el contenido del directorio:

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

Luego suelte las tablas:

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

Luego restaure con el archivo de copia de seguridad 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 tablas han sido restauradas.

Como podemos ver con pg_dump, puede hacer una copia de seguridad de una o varias tablas dentro de una base de datos específica.

Copia de seguridad de una base de datos

Veamos ahora cómo hacer una copia de seguridad de toda la base de datos 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

El archivo ex_back_db.sql está ahí.

Me conectaré a la base de datos postgres para eliminar la base de datos example_backups.

postgres=# DROP DATABASE example_backups;
DROP DATABASE

Luego restaure desde la línea de comandos:

$ 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

No está ahí. ¿Por qué no? ¿Y dónde está?

Tenemos que crearlo primero.

postgres=# CREATE DATABASE example_backups;
CREATE DATABASE

Luego restaure con el mismo 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)

Base de datos y todas las tablas presentes y contabilizadas.

Podemos evitar este escenario de tener que crear la base de datos de destino primero, al incluir la opción -C al realizar la copia de seguridad.

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

Volveré a conectarme a la base de datos de postgres y eliminaré la base de datos de ejemplo_copias de seguridad para que podamos ver cómo funciona la restauración ahora (tenga en cuenta que los comandos de conexión y DROP no se muestran por brevedad).

Luego, en la línea de comandos (observe que no se incluye la opción -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

Al usar la opción -C, se nos solicita una contraseña para establecer una conexión como se menciona en la documentación sobre el indicador -C:

"Comience la salida con un comando para crear la base de datos y vuelva a conectarse a la base de datos creada".

Luego, en la sesión de psql:

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

Todo está restaurado, listo para funcionar y sin necesidad de crear la base de datos de destino antes de la restauración.

pg_dumpall para todo el clúster

Hasta ahora, hemos respaldado una sola tabla, varias tablas y una sola base de datos.

Pero si queremos más que eso, por ejemplo, hacer una copia de seguridad de todo el clúster de PostgreSQL, ahí es donde debemos usar pg_dumpall.

Entonces, ¿cuáles son algunas diferencias notables entre pg_dump y pg_dumpall?

Para empezar, aquí hay una distinción importante de la documentación:

“Dado que pg_dumpall lee tablas de todas las bases de datos, lo más probable es que tenga que conectarse como superusuario de la base de datos para producir un volcado completo. Además, necesitará privilegios de superusuario para ejecutar el script guardado para poder agregar usuarios y grupos y crear bases de datos”.

Con el siguiente comando, haré una copia de seguridad de todo mi clúster de PostgreSQL y lo guardaré en el archivo 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:

¿Que demonios? ¿Se pregunta si tuve que ingresar una contraseña para cada solicitud?

Sí, claro que sí. 24 veces.

Cuéntalos. (Oye, ¿me gusta explorar y profundizar en diferentes bases de datos a medida que aprendo? ¿Qué puedo decir?)

Pero, ¿por qué todas las indicaciones?

En primer lugar, después de todo ese arduo trabajo, ¿pg_dumpall creó el archivo de copia de seguridad?

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

Sí, el archivo de copia de seguridad está ahí.

Vamos a arrojar algo de luz sobre toda esa 'práctica de mecanografía ' mirando este pasaje de la documentación:

“pg_dumpall necesita conectarse varias veces al servidor PostgreSQL (una vez por base de datos). Si utiliza la autenticación de contraseña, le pedirá una contraseña cada vez.”

Sé lo que estás pensando.

Esto puede no ser ideal o incluso factible. ¿Qué pasa con los procesos, scripts o trabajos cron que se ejecutan en medio de la noche?

¿Alguien va a pasar el cursor sobre el teclado, esperando para escribir?

Probablemente no.

Una medida eficaz para evitar que se le solicite repetidamente la contraseña es un archivo ~/.pgpass.

Esta es la sintaxis que el archivo ~/.pgpass requiere para funcionar (ejemplo proporcionado en la documentación, consulte el enlace anterior):

hostname:port:database:username:password

Con un archivo ~/.pgpass presente en mi entorno de desarrollo, que contiene las credenciales necesarias para el rol de postgres, puedo omitir la opción -W (también -w) y ejecutar pg_dumpall sin autenticar manualmente con la contraseña:

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

Listado del contenido del directorio:

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

El archivo se crea y no se repiten las solicitudes de contraseña.

El archivo guardado se puede volver a cargar con psql similar a pg_dump.

La base de datos de conexión también es menos crítica según este pasaje de la documentación:"No es importante a qué base de datos se conecte aquí, ya que el archivo de script creado por pg_dumpall contendrá los comandos apropiados para crear y conectarse a las bases de datos guardadas". /P> Descargue el documento técnico hoy Gestión y automatización de PostgreSQL con ClusterControl Obtenga información sobre lo que necesita saber para implementar, monitorear, administrar y escalar PostgreSQLDescargar el documento técnico

pg_dump, pg_dumpall y shell scripts:una combinación práctica

En esta sección, veremos un par de ejemplos de incorporación de pg_dump y pg_dumpall en scripts de shell simples.

Que quede claro, este no es un tutorial de script de shell. Tampoco soy un gurú de los scripts de shell. Proporcionaré principalmente un par de ejemplos que utilizo en mi entorno local de desarrollo/aprendizaje.

Primero, veamos un script de shell simple que puede usar para hacer una copia de seguridad de una sola base de datos:

#!/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 puede ver, este script acepta 2 argumentos:el primero es el usuario (o rol) con el que conectarse para la copia de seguridad, mientras que el segundo es el nombre de la base de datos que desea respaldar.

Observe la opción -C en el comando para que podamos restaurar si la base de datos no existe, sin la necesidad de crearla manualmente de antemano.

Llamemos al script con el rol postgres para la base de datos example_backups (no olvide hacer que el script sea ejecutable con al menos chmod +x antes de llamar por primera vez):

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

Y verifica que esté ahí:

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

La restauración se realiza con este script de copia de seguridad como en los ejemplos anteriores.

Se puede usar un script de shell similar con pg_dumpall para hacer una copia de seguridad de todo el clúster de PostgreSQL.

Este script de shell canalizará (|) pg_dumpall a gzip, que luego se dirige a una ubicación de archivo designada:

#!/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 diferencia del script de ejemplo anterior, este no acepta ningún argumento.

Llamaré a este script en la línea de comandos (no se solicita contraseña ya que el rol de postgres utiliza el archivo ~/.pgpass; consulte la sección anterior).

$ ~/My_Scripts/pgalldmp.sh

Una vez completado, enumeraré el contenido del directorio y también mostraré los tamaños de los archivos para compararlos entre los archivos .sql y 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 para el formato de archivo gz de los documentos:

"Los formatos de archivo de almacenamiento alternativos deben usarse con pg_restore para reconstruir la base de datos".

Resumen

Reuní puntos clave de la documentación en pg_dump y pg_dumpall, junto con mis observaciones, para cerrar esta publicación de blog:

Nota:Los puntos proporcionados de la documentación están entre comillas.

  • “pg_dump solo vuelca una única base de datos”
  • El formato de archivo SQL de texto sin formato es la salida predeterminada para pg_dump.
  • Un rol necesita el privilegio SELECT para ejecutar pg_dump de acuerdo con esta línea en la documentación:“pg_dump ejecuta internamente instrucciones SELECT. Si tiene problemas para ejecutar pg_dump, asegúrese de poder seleccionar información de la base de datos usando, por ejemplo, psql”
  • Para incluir el comando DDL CREATE DATABASE necesario y una conexión en el archivo de respaldo, incluya la opción -C.
  • -W:esta opción obliga a pg_dump a solicitar una contraseña. Este indicador no es necesario ya que si el servidor requiere una contraseña, se le solicitará de todos modos. Sin embargo, este pasaje en la documentación me llamó la atención, así que pensé en incluirlo aquí:“Sin embargo, pg_dump desperdiciará un intento de conexión al descubrir que el servidor quiere una contraseña. En algunos casos, vale la pena escribir -W para evitar el intento de conexión adicional”.
  • -d:especifica la base de datos a la que conectarse. También en la documentación:"Esto es equivalente a especificar dbname como el primer argumento que no es una opción en la línea de comando".
  • Usar indicadores como -t (tabla) permite a los usuarios hacer una copia de seguridad de partes de la base de datos, es decir, tablas, para las que tienen privilegios de acceso.
  • Los formatos de los archivos de copia de seguridad pueden variar. Sin embargo, los archivos .sql son una excelente opción entre otros. psql vuelve a leer los archivos de respaldo para una restauración.
  • pg_dump puede respaldar una base de datos activa y en ejecución sin interferir con otras operaciones (es decir, otros lectores y escritores).
  • Una advertencia:pg_dump no volca roles ni otros objetos de la base de datos, incluidos espacios de tabla, solo una única base de datos.
  • Para realizar copias de seguridad de todo su clúster de PostgreSQL, pg_dumpall es la mejor opción.
  • pg_dumpall puede manejar todo el clúster, respaldando información sobre roles, tablespaces, usuarios, permisos, etc... donde pg_dump no puede.
  • Lo más probable es que un rol con privilegios de SUPERUSUARIO tenga que realizar el volcado y restaurar/recrear el archivo cuando se vuelva a leer a través de psql porque durante la restauración, se requiere el privilegio de leer todas las tablas en todas las bases de datos.

Mi esperanza es que a través de esta publicación de blog, he proporcionado ejemplos y detalles adecuados para una descripción general de nivel principiante en pg_dump y pg_dumpall para un solo entorno de desarrollo/aprendizaje de PostgreSQL.

Aunque no se exploraron todas las opciones disponibles, la documentación oficial contiene una gran cantidad de información con ejemplos para ambas utilidades, así que asegúrese de consultar ese recurso para obtener más estudios, preguntas y lecturas.