Respaldo Continuo y Warm/Hot Standby

Las versiones más recientes de PostgreSql soportan varios modos de archivamiento (respaldo continuo) y servidores en espera (standby con recupero continuo)

Resumen de Modos de Operación:

  • Continuous Archiving(online backup): archivamiento continuo (respaldos de los segmentos de WAL)
  • Point-In-Time Recovery (PITR): recuperación en el tiempo (disaster recovery)
  • Warm-standby: archivamiento + recuperación continua (high availability)
  • Hot-standby: archivamiento + recuperación continua + consultas de solo lectura

Entorno

Para evitar errores, es conveniente definir las variables de entorno con directorios, binarios y configuraciones a utilizar:

export PGDATA=~/pg/data90
export PGBIN=~/pg/bin
export PGPORT=5485
export PGDATABASE=correo
export PGPORTNEW=5486

Configurar archivamiento

Para habilitar archivamiento en postgresql.conf, modificar las opciones de configuración:

wal_level = hot_standby # o archive 
archive_mode = on
archive_command = 'cp -i %p ../archive/%f </dev/null'  # Unix -i previene sobrescritura
#archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'  # Windows
archive_timeout = 60 # forzar archivar cada 1 minuto

Según el modo, establecer wal_level a archive (solo recuperación continua) o hot_standby para que se guarden en los segmentos la información necesaria.

El archive_command debe copiar los segmentos a un directorio accesible por el servidor.

Iniciar archivamiento

Para comenzar a archivar, crear un directorio para los segmentos y reiniciar el servidor para que tome el cambio de configuración:

mkdir archive
$PGBIN/pg_ctl -D $PGDATA restart

Asegurarse que se llene archivo

Verificar que comience a archivar, sino el directorio pg_xlog se llenará indefinidamente.

Se puede forzar la escritura de un segmento con pg_switch_xlog():

$PGBIN/psql -c "select pg_switch_xlog()"

Si el archivamiento funciona, un ls archive debería mostrar los segmentos copiados:

000000010000000000000004
000000010000000000000005

Iniciar respaldo

Una vez comenzado el modo de archivamiento, se debe indicar al servidor que se realizará un respaldo base que sea consistente mediante la función pg_start_backup().

El primer parámetro de la función es la etiqueta para marcar el backup. Este proceso puede demorar por checkpoint i/o, sino usar 2do param en true.

$PGBIN/psql postgres -c "SELECT pg_start_backup('respaldo');"

La salida esperada sería el punto de inicio del backup (se puede ignorar el resultado):

 pg_start_backup 
-----------------
 0/5000020
(1 fila)

Copiar físicamente archivos respaldo base

Luego de indicar al servidor que comienza el backup, se debe realizar la copia de los archivos físicamente, por ej. con las siguientes órdenes:

mkdir respaldo
chmod 700 respaldo
cd $PGDATA ; cp -rvdpaf !(pg_xlog) ../respaldo; cd ..

También podría usarse tar, rsync o similar.

Detener respaldo consistente

Terminada la copia física de los archivos, se debe indicar que finaliza el backup con pg_stop_backup():

$PGBIN/psql postgres -c "select pg_stop_backup(), current_timestamp"

cuya salida será:

NOTICE:  pg_stop_backup completado, todos los segmentos de WAL requeridos han sido archivados
 pg_stop_backup |              now              
----------------+-------------------------------
 0/9000044      | 2010-12-28 01:42:12.138907-03
(1 fila)

Configurar recovery (en respaldo)

Cuando se desee recuperar el servidor de respaldo, se debe crear un archivo recovery.conf que indica al motor como realizar el proceso:

cat << eof > respaldo/recovery.conf
restore_command = 'cp ../archive/%f %p'
standby_mode = 'on' # recuperación continua, comentar si se des
eof

Para detener la recuperación en un momento específico (PITR), utilizar las siguientes opciones de configuración en recovery.conf:

#recovery_target_time = ''      # e.g. '2004-07-14 22:39:00 EST'
#recovery_target_xid = ''
#recovery_target_inclusive = 'true'
#recovery_target_timeline = 'latest'

Si la recuperación se realiza en el mismo equipo, cambiar en respaldo/postgresql.conf la configuración general y desactivar el archivamiento:

port = 5486	# (para esta prueba, deshabilitar accesos si corresponde) 
hot_standby = on # habilitar consultas de solo lectura
archive_mode = off

Recuperar

Una vez configurado el servidor de respaldo, para iniciar el proceso de recuperación iniciar el motor (previa limpieza del directorio de datos):

rm respaldo/postmaster.pid  # borrar pid del principal
rm respaldo/pg_xlog -Rv
mkdir respaldo/pg_xlog      # recrear directorio WAL
bin/pg_ctl -D respaldo start

La salida esperada (en modo de recuperación normal) sería:

servidor iniciándose
reingart@eepc:~/pg$ LOG:  el sistema de bases de datos fue interrumpido; última vez en funcionamiento en 2010-12-28 01:40:47 ART
LOG:  creando el directorio WAL faltante «pg_xlog/archive_status»
LOG:  comenzando proceso de recuperación
LOG:  se ha restaurado el archivo «000000010000000000000005» desde el área de archivado
LOG:  redo comienza en 0/5000070
LOG:  se ha restaurado el archivo «000000010000000000000006» desde el área de archivado
LOG:  se ha restaurado el archivo «000000010000000000000007» desde el área de archivado
LOG:  se ha restaurado el archivo «000000010000000000000008» desde el área de archivado
LOG:  se ha restaurado el archivo «000000010000000000000009» desde el área de archivado
LOG:  el estado de recuperación consistente fue alcanzado en 0/A000000
LOG:  se ha restaurado el archivo «00000001000000000000000A» desde el área de archivado
LOG:  se ha restaurado el archivo «00000001000000000000000B» desde el área de archivado
LOG:  se ha restaurado el archivo «00000001000000000000000C» desde el área de archivado
LOG:  se ha restaurado el archivo «00000001000000000000000D» desde el área de archivado
cp: no se puede efectuar «stat» sobre «../archive/00000001000000000000000E»: No existe el archivo o directorio
LOG:  no se pudo abrir «pg_xlog/00000001000000000000000E» (archivo de registro 0, segmento 14): No existe el archivo o directorio
LOG:  redo listo en 0/D3F4834
LOG:  última transacción completada al tiempo de registro 2010-12-28 01:52:06.098197-03
LOG:  se ha restaurado el archivo «00000001000000000000000D» desde el área de archivado
cp: no se puede efectuar «stat» sobre «../archive/00000002.history»: No existe el archivo o directorio
LOG:  seleccionado nuevo ID de timeline: 2
cp: no se puede efectuar «stat» sobre «../archive/00000001.history»: No existe el archivo o directorio
LOG:  recuperación completa

Los errores de `cp' generalmente son inofensivos y señalan donde termina la recuperación (hasta que segmento de WAL se ha copiado y recuperado).

En modo de recuperación continua, la salida varía:

LOG:  el sistema de bases de datos fue apagado durante la recuperación en 2010-12-28 03:57:43 ART
LOG:  entrando al modo standby
LOG:  se ha restaurado el archivo «00000001000000000000002F» desde el área de archivado
LOG:  redo comienza en 0/2F000020
LOG:  el estado de recuperación consistente fue alcanzado en 0/30000000
LOG:  el sistema de bases de datos está listo para aceptar conexiones de sólo lectura
cp: no se puede efectuar «stat» sobre «../archive/000000010000000000000030»: No existe el archivo o directorio
cp: no se puede efectuar «stat» sobre «../archive/000000010000000000000030»: No existe el archivo o directorio

Inspeccionar respaldo actualizaciones

Para probar la recuperación continua, en el servidor principal se puede correr pgbench para generar datos de prueba, forzar el transpaso de segmento de wal y verificar en el respaldo:

$PGBIN/psql -c "select count(*) from pgbench_history"
$PGBIN/pgbench -t 1000 -p 5485 correo
$PGBIN/psql -c "select count(*) from pgbench_history"
$PGBIN/psql -c "select pg_switch_xlog()"
$PGBIN/psql -p $PGPORTNEW -c "select count(*) from pgbench_history"

La salida debería indicar los registros modificados:

 count 
-------
  1000
(1 fila)

Consejos ("TIPs")

Al utilizar recuperación continua:

  • Usar REINDEX indices hash (no pasan por la WAL)
  • No modificar templates al tomar el backup base
  • Nuevos tablespaces -> rehacer backup base
  • Comprimir segmentos WAL con  pg_lesslog

Bibliografía

Para mayor información dirigirse a: