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

Implementación de Switchover/Switchback en PostgreSQL 9.3.

Esta publicación educa a los DBA sofisticados sobre cómo configurar un entorno Switchover y Switchback elegante en la alta disponibilidad de PostgreSQL. En primer lugar, gracias a los autores del parche, Heikki y Fujii, por hacer que Switchover/Switchback sea más fácil en PostgreSQL 9.3 (perdónenme si me olvidé de otros nombres).

Permítanme intentar ilustrarlo brevemente antes de estos parches, todos ustedes saben que los Standby son componentes críticos para lograr una recuperación ante desastres rápida y segura. En PostgreSQL, el concepto de recuperación se ocupa principalmente de las líneas de tiempo para identificar una serie de segmentos WAL antes y después del PITR o la promoción de Standby para evitar la superposición de segmentos WAL. La ID de la línea de tiempo está asociada con los nombres de archivo del segmento WAL (por ejemplo:en $PGDATA/pg_xlog/0000000C000000020000009E, el segmento "0000000C" es la ID de la línea de tiempo). En Streaming Replication, tanto el principal como el esclavo seguirán la misma ID de línea de tiempo, sin embargo, cuando Standby obtiene la promoción como nuevo maestro mediante Switchover, supera la ID de línea de tiempo y el principal antiguo se niega a reiniciar como Standby debido a la diferencia de ID de línea de tiempo y arroja un mensaje de error como:

FATAL:  requested timeline 10 is not a child of this server's history
DETAIL: Latest checkpoint is at 2/9A000028 on timeline 9, but in the history of the requested timeline, the server forked off from that timeline at 2/99017E68.

Por lo tanto, se debe construir un nuevo Standby desde cero, si el tamaño de la base de datos es enorme, entonces se necesita más tiempo para reconstruir y, durante este período, el recién ascendido Primario se ejecutará sin Standby. También hay otro problema como, cuando ocurre el cambio, el primario realiza un apagado limpio, el proceso de Walsender envía todos los registros WAL pendientes al modo de espera, pero no espera a que se repliquen antes de salir. Walreceiver no aplica esos registros WAL pendientes ya que detecta el cierre de la conexión y sale.

En la actualidad, con dos actualizaciones de software clave en PostgreSQL 9.3, ambos problemas se abordaron muy bien por los autores y ahora Streaming Replication Standby sigue un cambio de línea de tiempo consistente. Ahora podemos cambiar sin problemas y sin problemas las tareas entre Primaria y Standby simplemente reiniciando y reduciendo en gran medida el tiempo de reconstrucción de Standby.

Nota:No es posible cambiar/revertir si los archivos WAL no son accesibles para ambos servidores y en el proceso de cambio La base de datos principal debe realizar un apagado limpio (modo normal o rápido).

Para hacer una demostración, comencemos con la configuración de Streaming Replication (wiki para configurar SR) que configuré en mi máquina virtual local entre dos clústeres (5432 como primario y 5433 como en espera) que comparten una ubicación común de archivos WAL, porque ambos clústeres deberían tener acceso completo de secuencia de archivos WAL. Mire la instantánea compartida a continuación con los detalles de configuración y la identificación de la línea de tiempo actual para comprender mejor el concepto.

En esta etapa, todos deben tener una comprensión sólida de que Switchover y Switchback son actividades planificadas. Ahora que la configuración de SR está en su lugar, podemos intercambiar las funciones de principal y de reserva como se muestra a continuación:

Pasos de cambio:

Paso 1. Realice un apagado limpio de Primary[5432] (-m rápido o inteligente)

[postgres@localhost:/~]$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data stop -mf
waiting for server to shut down.... done
server stopped

Paso 2. Compruebe el estado de sincronización y el estado de recuperación de Standby[5433] antes de promocionarlo:

[postgres@localhost:/opt/PostgreSQL/9.3~]$  psql -p 5433 -c 'select pg_last_xlog_receive_location() "receive_location",
pg_last_xlog_replay_location() "replay_location",
pg_is_in_recovery() "recovery_status";'
receive_location | replay_location | recovery_status
------------------+-----------------+-----------------
2/9F000A20 | 2/9F000A20 | t
(1 row)

En espera en completa sincronización. En esta etapa, podemos promoverlo como principal.
Paso 3. Abra Standby como nuevo principal promoviendo pg_ctl o creando un archivo de activación.

[postgres@localhost:/opt/PostgreSQL/9.3~]$ grep trigger_file data_slave/recovery.conf
trigger_file = '/tmp/primary_down.txt'
[postgres@localhost:/opt/PostgreSQL/9.3~]$ touch /tmp/primary_down.txt

[postgres@localhost:/opt/PostgreSQL/9.3~]$ psql -p 5433 -c "select pg_is_in_recovery();"
pg_is_in_recovery
-------------------
f
(1 row)

In Logs:
2014-12-29 00:16:04 PST-26344-- [host=] LOG: trigger file found: /tmp/primary_down.txt
2014-12-29 00:16:04 PST-26344-- [host=] LOG: redo done at 2/A0000028
2014-12-29 00:16:04 PST-26344-- [host=] LOG: selected new timeline ID: 14
2014-12-29 00:16:04 PST-26344-- [host=] LOG: restored log file "0000000D.history" from archive
2014-12-29 00:16:04 PST-26344-- [host=] LOG: archive recovery complete
2014-12-29 00:16:04 PST-26342-- [host=] LOG: database system is ready to accept connections
2014-12-29 00:16:04 PST-31874-- [host=] LOG: autovacuum launcher started

El modo de espera se promocionó como maestro y se siguió una nueva línea de tiempo que puede observar en los registros.
Paso 4. Reinicie el primario antiguo como modo de espera y permita seguir la nueva línea de tiempo pasando "recovery_target_timline='latest'" en el archivo $PGDATA/recovery.conf.

[postgres@localhost:/opt/PostgreSQL/9.3~]$ cat data/recovery.conf
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=localhost port=5433 user=postgres'
restore_command = 'cp /opt/PostgreSQL/9.3/archives93/%f %p'
trigger_file = '/tmp/primary_131_down.txt'
[postgres@localhost:/opt/PostgreSQL/9.3~]$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data start
server starting

Si revisa recovery.conf, es muy claro que el principal antiguo intenta conectarse al puerto 5433 como el nuevo modo de espera que apunta a la ubicación común de los archivos WAL y se inició.

In Logs:
2014-12-29 00:21:17 PST-32315-- [host=] LOG: database system was shut down at 2014-12-29 00:12:23 PST
2014-12-29 00:21:17 PST-32315-- [host=] LOG: restored log file "0000000E.history" from archive
2014-12-29 00:21:17 PST-32315-- [host=] LOG: entering standby mode
2014-12-29 00:21:17 PST-32315-- [host=] LOG: restored log file "0000000D00000002000000A0" from archive
2014-12-29 00:21:17 PST-32315-- [host=] LOG: restored log file "0000000D.history" from archive
2014-12-29 00:21:17 PST-32315-- [host=] LOG: consistent recovery state reached at 2/A0000090
2014-12-29 00:21:17 PST-32315-- [host=] LOG: record with zero length at 2/A0000090
2014-12-29 00:21:17 PST-32310-- [host=] LOG: database system is ready to accept read only connections
2014-12-29 00:21:17 PST-32325-- [host=] LOG: started streaming WAL from primary at 2/A0000000 on timeline 14

Paso 5. Verifique el nuevo estado de suspensión.

[postgres@localhost:/opt/PostgreSQL/9.3~]$ psql -p 5432 -c "select pg_is_in_recovery();"
pg_is_in_recovery
-------------------
t
(1 row)

Genial, sin ninguna reconfiguración, hemos recuperado el principal antiguo como el nuevo modo de espera.

Pasos de retroceso:

Paso 1. Realice un apagado limpio del nuevo primario [5433]:

[postgres@localhost:/opt/~]$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data_slave stop -mf
waiting for server to shut down.... done
server stopped

Paso 2. Verifique el estado de sincronización del nuevo Standby [5432] antes de promoverlo.
Paso 3. Abra el nuevo modo de espera [5432] como principal creando un archivo de activación o promoviendo pg_ctl.

[postgres@localhost:/opt/PostgreSQL/9.3~]$ touch /tmp/primary_131_down.txt

Paso 4. Reinicie el nuevo Primario detenido [5433] como nuevo Standby.

[postgres@localhost:/opt/PostgreSQL/9.3~]$ more data_slave/recovery.conf
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=localhost port=5432 user=postgres'
restore_command = 'cp /opt/PostgreSQL/9.3/archives93/%f %p'
trigger_file = '/tmp/primary_down.txt'

[postgres@localhost:/opt/PostgreSQL/9.3~]$ /opt/PostgreSQL/9.3/bin/pg_ctl -D /opt/PostgreSQL/9.3/data_slave start
server starting

Puede verificar los registros del nuevo Standby.

In logs:
[postgres@localhost:/opt/PostgreSQL/9.3/data_slave/pg_log~]$ more postgresql-2014-12-29_003655.log
2014-12-29 00:36:55 PST-919-- [host=] LOG: database system was shut down at 2014-12-29 00:34:01 PST
2014-12-29 00:36:55 PST-919-- [host=] LOG: restored log file "0000000F.history" from archive
2014-12-29 00:36:55 PST-919-- [host=] LOG: entering standby mode
2014-12-29 00:36:55 PST-919-- [host=] LOG: restored log file "0000000F.history" from archive
2014-12-29 00:36:55 PST-919-- [host=] LOG: restored log file "0000000E00000002000000A1" from archive
2014-12-29 00:36:55 PST-919-- [host=] LOG: restored log file "0000000E.history" from archive
2014-12-29 00:36:55 PST-919-- [host=] LOG: consistent recovery state reached at 2/A1000090
2014-12-29 00:36:55 PST-919-- [host=] LOG: record with zero length at 2/A1000090
2014-12-29 00:36:55 PST-914-- [host=] LOG: database system is ready to accept read only connections
2014-12-29 00:36:55 PST-929-- [host=] LOG: started streaming WAL from primary at 2/A1000000 on timeline 15
2014-12-29 00:36:56 PST-919-- [host=] LOG: redo starts at 2/A1000090

Muy bien, sin mucho tiempo hemos cambiado las funciones de los servidores principal y de reserva. Incluso puede notar el incremento de las ID de la línea de tiempo de los registros para cada promoción.

Al igual que otros, todas mis publicaciones son parte del intercambio de conocimientos, cualquier comentario o corrección es bienvenido. 🙂