Breve introducción a pg_basebackup
El comando pg_basebackup permite crear un backup en caliente del sistema de fichero de una Instancia de PostgreSQL (lo que se llama un Backup Base, es decir, el contenido del directorio data) a través de una conexión de base de datos, utilizando el protocolo de replicación.
Como consecuencia de esto, al ejecutar el comando pg_basebackup deberemos especificar los datos de conexión a PostgreSQL (por defecto intentará conectarse a localhost en el puerto 5432 con el usuario actual), en lugar de tener que especificar el directorio data.
Pero además, si no lo hemos hecho antes, deberemos de configurar el fichero pg_hba.conf para permitir la replicación (requiere reiniciar la Instancia para que tome efecto), ya que por defecto viene deshabilitado, y en estas condiciones si intentamos ejecutar el comando pg_basebackup podríamos obtener un error como el siguiente: pg_basebackup: could not connect to server: FATAL: no pg_hba.conf entry for replication connection from host "[local]", user "postgres", SSL off
Además, el comando pg_basebackup utiliza al menos una sesión de WAL Senders, por lo que si no lo hemos hecho antes, deberemos configurar el fichero postgresql.conf para establecer un valor correcto del parámetro max_wal_senders (requiere reiniciar la Instancia para que tome efecto), ya que por defecto su valor es cero (la replicación está deshabilitada). De lo contrario, al intentar utilizar el comando pg_basebackup podríamos obtener un error como el siguiente: pg_basebackup: could not connect to server: FATAL: number of requested standby connections exceeds max_wal_senders (currently 0)
Hay que tener en cuenta que el comando pg_basebackp utiliza una conexión, por lo que si no estamos utilizando la replicación (como en nuestro caso de ejemplo), con establecer max_wal_senders a 1 es más que suficiente. Sin embargo, si deseamos utilizar la opción --xlog-method=stream para incluir las transacciones (WAL) en nuestro Backup sin tener problemas de rotados de WAL, necesitaremos establecer una segunda conexión de replicación, por lo que deberemos aumentar el valor de max_wal_senders (por ejemplo a 2, en nuestro caso de ejemplo que no utilizamos la replicación).
El comando pg_basebackup puede verse como una evolución de la forma tradicional de hacer Backup, resultando más sencillo, ya que ahora con un único comando obtenemos nuestro Backup, sin tener que invocar manualmente a las funciones pg_start_backup y pg_stop_backup, para adicionalmente hacer la copia de ficheros. En cualquier caso, antes de continuar con la lectura del presente artículo, es muy recomendable leer el artículo anterior PostgreSQL: Hot Physical Backup and Restore.
Descripción del Escenario
Partimos de una instalación del PostgreSQL 9.2.18 con archivado de WAL comprimido sobre Centos7 utilizando únicamente los tablespaces por defecto. Las principales rutas son las siguientes:
- Directorio Data: /var/lib/pgsql/data
- Directorio Archivado de WAL comprimido: /var/lib/pgsql/PostgresqlWalCompr
- Directorio para almacenar los Backups: /var/lib/pgsql/PostgresqlBackup
La configuración del archivado de WAL en el fichero postgresql.conf es la siguiente:
wal_level = archive archive_mode = on archive_command = '/usr/local/bin/omnipitr-archive -D /var/lib/pgsql/data -l /var/log/wal/wal.log -dl gzip=/var/lib/pgsql/PostgresqlWalCompr -v "%p"' |
Sobre este escenario, vamos a realizar las pruebas que detallamos a continuación.
Backup listo para recuperar (Ready to Restore) a un directorio con pg_basebackup copiando los WAL al final (-x), ojo con wal_keep_segments
El comando pg_basebackup por defecto no incluye el contenido del directorio pg_log, es decir, no incluye los WAL, por lo que el backup generado no será recuperable por sí sólo y necesitaremos adicionalmente tener Backup de los WAL para poder restaurar con éxito (habitualmente de los WAL archivados).
Sin embargo, es posible hacer un Backup recuperable por sí solo (ready to restore) con pg_basebackup utilizando la opción -x, que incluirá la información de los WAL (directorio pg_log), y así evitaremos dependencias con el archivado de los WAL y simplificaremos el proceso de backup y de recuperación.
IMPORTANTE: Al utilizar la opción -x los WAL son recopilados al final del Backup, por lo tanto, el parámetro de configuración wal_keep_segments debe tener un valor suficientemente alto para que los WAL no sean eliminados/archivados antes de que finalice el Backup.
A continuación podemos ver un comando de ejemplo.
cd /var/lib/pgsql pg_basebackup -l "Daily Backup" -x -D ./PostgresqlBackup/pg_basebackup
|
La ejecución del anterior comando creará un directorio con la copia del directorio data, así como con la información de los WAL necesarios para la recuperación, tal y como se puede observar en el siguiente pantallazo.
El proceso de recuperación es muy sencillo. Parar PostgreSQL, eliminar o mover el directorio data actual, copiar o mover el directorio data del Backup, y arrancar PostgreSQL. La siguiente secuencia de comandos sería un ejemplo práctico.
pg_ctl -D /var/lib/pgsql/data -m fast stop cd /var/lib/pgsql mkdir ./data.old mv /var/lib/pgsql/data/* /var/lib/pgsql/data.old/ cp -r ./PostgresqlBackup/pg_basebackup/* ./data/ pg_ctl -D /var/lib/pgsql/data start |
Backup listo para recuperar (Ready to Restore) a un tar comprimido con pg_basebackup copiando los WAL al final (-x), ojo con wal_keep_segments
Hacer un backup a un directorio tiene el inconveniente de que el tamaño del Backup puede ser demasiado grande, por lo que habitualmente se prefiere hacer el backup a un fichero tar comprimido (ej: tar.gz), de tal modo que podamos minimizar el espacio en disco necesario, así como el tiempo de transferencia del Backup en caso de tener que copiarlo. De nuevo, vamos a utilizar la opción -x (ojo con wal_keep_segments) para realizar la copia de los WAL al final del Backup. La única diferencia, es que en este caso, haremos el Backup a un tar comprimido. A continuación se puede ver un ejemplo del comando a ejecutar.
cd /var/lib/pgsql pg_basebackup -l "Daily Backup" -x -D ./PostgresqlBackup/pg_basebackup -Ft -z
|
La siguiente pantalla capturada muestra la salida de ejecución del anterior comando. Como podemos observar, se ha generado un fichero comprimido con nombre base.tar.gz.
El proceso de recuperación es similar al caso anterior, en el que hicimos el Backup a un directorio, pero incluyendo algún paso adicional para descomprimir y borrar después el fichero tar.gz. A continuación se muestra una secuencia de comandos de ejemplo.
pg_ctl -D /var/lib/pgsql/data -m fast stop cd /var/lib/pgsql mkdir ./data.old mv /var/lib/pgsql/data/* /var/lib/pgsql/data.old/ cp ./PostgresqlBackup/pg_basebackup/base.tar.gz ./data/ cd data tar -xvf base.tar.gz rm base.tar.gz pg_ctl -D /var/lib/pgsql/data start
|
En la siguiente pantalla capturada se puede observar el resultado de ejecución de la anterior secuencia de comandos (hemos omitido la opción verbose al descomprimir el tar, para que quede más claro).
Backup listo para recuperar (Ready to Restore) a un directorio con pg_basebackup copiando los WAL por streaming (evitando problemas de wal_keep_segments)
En los ejemplos anteriores veíamos como crear un Backup listo para recuperar (Ready to Restore) con pg_basebackup utilizando la opción -x para copiar los WAL al final del Backup, lo cual nos permite tanto hacer un Backup a un directorio como a un tar comprimido. Sin embargo, tiene el inconveniente de que podríamos tener problemas derivados del rotado de WALs de tal modo que nos falte algún fichero WAL en nuestro Backup, en cuyo caso no podríamos recuperarlo con éxito (excepto con una intervención manual en la que necesitaríamos los WAL), situación que podríamos intentar evitar ajustando el valor de configuración del parámetro wal_keep_segments.
Una alternativa para conseguir un Backup listo para recuperar (con información de los WAL) sin depender del parámetro wal_keep_segments (evitando el riesgo derivado del rotado de los WAL) es utilizar la opción --xlog-method=stream. Al utilizar esta opción, el comando pg_basebackup crea una conexión secundaria para obtener los WAL necesarios por streaming, de tal modo que obtendremos un Backup completo que incluirá la información de todas las transacciones necesarias para su recuperación. El principal inconveniente, que sólo es posible realizar el Backup a un directorio, es decir, no es posible hacer el Backup a un tar ni a un tar comprimido. A continuación se muestra un comando de ejemplo, incluyendo la opción -P para informar del progreso del backup.
cd /var/lib/pgsql pg_basebackup -l "Daily Backup" --xlog-method=stream -D ./PostgresqlBackup/pg_basebackup -P
|
La siguiente pantalla capturada muestra un ejemplo de ejecución del anterior comando de Backup.
El procedimiento de recuperación es el mismo que ya vimos anteriormente para la recuperación desde un Backup a directorio. Igualmente, no es necesario preparar el fichero recovery.conf. En resumidas cuentas, paramos PostgreSQL, copiamos ficheros, arrancamos, y ya está. A continuación mostramos una secuecuencia de comandos de ejemplo.
pg_ctl -D /var/lib/pgsql/data -m fast stop cd /var/lib/pgsql mkdir ./data.old mv /var/lib/pgsql/data/* /var/lib/pgsql/data.old/ cp -r ./PostgresqlBackup/pg_basebackup/* ./data/ pg_ctl -D /var/lib/pgsql/data start
|
Despedida y Cierre
Hasta aquí llega el presente artículo, en el que hemos podido ver las diferentes alternativas para crear un Backup listo para recuperar (Ready to Restore) con el comando pg_basebackup. Antes de finalizar aprovecho para compartir varios enlaces de interés, para quien desee ampliar más información:
Poco más por hoy. Como siempre, confío que la lectura resulte de interés.