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

Switchover/Switchback en Slony-I mientras se actualizan las versiones principales de PostgreSQL 8.4.x/9.3.x

Cada nueva versión de PostgreSQL viene con un montón de características interesantes. Para beneficiarse de las nuevas funciones, se debe actualizar el servidor de la base de datos. Elegir rutas de actualización tradicionales como pg_dump/pg_restore o pg_upgrade requiere un tiempo de inactividad significativo de la aplicación. Hoy en día, si está buscando una ruta de actualización de tiempo de inactividad mínimo entre las principales versiones de PostgreSQL con un plan de reversión perfecto, entonces se logrará mediante la replicación asíncrona Slony-I. Dado que Slony-I (conozca más sobre esto aquí) tiene la capacidad de replicar fácilmente entre diferentes versiones de PostgreSQL, OS y arquitecturas de bits, las actualizaciones son factibles sin requerir un tiempo de inactividad sustancial. Además, tiene una funcionalidad de cambio y retroceso constante en su diseño.

En mi opinión, al realizar actualizaciones de versiones principales, debe haber un plan de respaldo adecuado porque, en caso de que la aplicación tenga errores o no funcione bien en la versión actualizada, entonces deberíamos poder retroceder a la versión anterior de inmediato. Slony-I proporciona dicha funcionalidad en la forma de retroceso. Esta publicación demuestra una actualización mínima del tiempo de inactividad, incluidos los pasos de conmutación/retroceso.

Antes de ir a la demostración, se debe tener en cuenta un paso importante, antes de la versión PG 9.0.x, las columnas de tipo de datos bytea se usan para almacenar datos en formato ESCAPE y la versión posterior está en formato HEX. Al realizar el cambio (versión más nueva a la versión anterior), Slony-I no admite este tipo de diferencias de formato bytea, por lo tanto, el formato ESCAPE debe mantenerse durante la duración de la actualización; de lo contrario, puede encontrar un error:

ERROR  remoteWorkerThread_1_1: error at end of COPY IN: ERROR:  invalid input syntax for type bytea
CONTEXT: COPY sl_log_1, line 1: "1 991380 1 100001 public foo I 0 {id,500003,name,"A ",b,"\\x41"}"
ERROR remoteWorkerThread_1: SYNC aborted

Para solucionarlo, no se requieren cambios en PG 8.4.x pero en PG 9.3.5 el parámetro bytea_output debe configurarse de HEX a ESCAPE como se muestra. Podemos configurarlo a nivel de clúster ($PGDATA/postgresql.conf) o a nivel de usuario (ALTER TABLE…SET), he preferido ir con cambios a nivel de usuario.

slavedb=# alter user postgres set bytea_output to escape;
ALTER ROLE

Procedamos con los pasos de actualización. A continuación se muestran los detalles del servidor de mis dos versiones utilizadas en esta demostración, cámbielo según la configuración de su servidor si lo está intentando:

Origin Node (Master/Primary are called as Origin)                     Subscriber Node (Slave/Secondary are called as Subscriber)
------------------------------------------------- ----------------------------------------------------------
Host IP : 192.168.22.130 192.168.22.131
OS Version : RHEL 6.5 64 bit RHEL 6.5 64 bit
PG Version : 8.4.22 (5432 Port) 9.3.5 (5432 Port)
Slony Vers. : 2.2.2 2.2.2
PG Binaries : /usr/local/pg84/bin /opt/PostgreSQL/9.3/
Database : masterdb slavedb
PK Table : foo(id int primary key, name char(20), image bytea) ...restore PK tables structure from Origin...

Para una comprensión simple y una implementación fácil, he dividido la demostración en tres secciones

1. Compilación de binarios Slony-I contra versiones de PostgreSQL
2. Creación de scripts de replicación y ejecución
3. Prueba de conmutación/retroceso.

1. Compilación de binarios Slony-I contra la versión de PostgreSQL
Descargue las fuentes de Slony-I desde aquí y realice la instalación de la fuente contra los binarios de PostgreSQL en los nodos de origen y suscriptor.

On Origin Node:
# tar -xvf slony1-2.2.2.tar.bz2
# cd slony1-2.2.2
./configure --with-pgbindir=/usr/local/pg84/bin
--with-pglibdir=/usr/local/pg84/lib
--with-pgincludedir=/usr/local/pg84/include
--with-pgpkglibdir=/usr/local/pg84/lib/postgresql
--with-pgincludeserverdir=/usr/local/pg84/include/postgresql/
make
make install

On Subscriber Node: (assuming PG 9.3.5 installed)
# tar -xvf slony1-2.2.2.tar.bz2
# cd slony1-2.2.2
./configure --with-pgconfigdir=/opt/PostgreSQL/9.3/bin
--with-pgbindir=/opt/PostgreSQL/9.3/bin
--with-pglibdir=/opt/PostgreSQL/9.3/lib
--with-pgincludedir=/opt/PostgreSQL/9.3/include
--with-pgpkglibdir=/opt/PostgreSQL/9.3/lib/postgresql
--with-pgincludeserverdir=/opt/PostgreSQL/9.3/include/postgresql/server/
--with-pgsharedir=/opt/PostgreSQL/9.3/share
make
make install

2. Creación de scripts de replicación y ejecución
Para configurar la replicación, necesitamos crear algunos scripts que se ocupen de la replicación, incluido el cambio/retroceso.

1. initialize.slonik:este script contiene la información de conexión de los nodos de origen/suscriptor.
2. create_set.slonik:este script contiene todas las tablas PK de origen que se replican en el nodo de suscriptor.
3. subscribe_set.slonik:este script comienza a replicar datos de conjuntos en el nodo de suscriptor.
4. switchover.slonik:este script ayuda a mover el control del origen al suscriptor.
5. switchback.slonik:este script ayuda a controlar desde el suscriptor hasta el origen.

Finalmente, dos scripts de inicio más “start_OriginNode.sh” y “start_SubscriberNode.sh” que inicia procesos de slon de acuerdo con los binarios compilados en los nodos de origen/suscriptor.

Descargue todos los scripts desde aquí.

Aquí están los datos de muestra en el nodo de origen (8.4.22) en Foo Table con una columna de tipo de datos bytea, que replicaremos en el nodo de suscriptor (9.3.5) con la ayuda de los scripts creados.

masterdb=# select * from foo;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
(3 rows)

Llamemos a los scripts uno por uno para configurar la replicación. RECUERDE TODO EL GUIÓN DE SLONIK DEBE EJECUTARSE SOLO EN EL NODO DE ORIGEN, EXCEPTO "start_OriginNode.sh" Y "start_SubscriberNode.sh" QUE DEBEN EJECUTARSE INDIVIDUALMENTE.

-bash-4.1$ slonik initalize.slonik
-bash-4.1$ slonik create_set.slonik
create_set.slonik:13: Set 1 ...created
create_set.slonik:16: PKey table *** public.foo *** added.
-bash-4.1$ sh start_OriginNode.sh
-bash-4.1$ sh start_SubscriberNode.sh //ON SUBSCRIBER NODE
-bash-4.1$ slonik subscribe_set.slonik

Después de la ejecución exitosa del script anterior, puede notar que los datos en Origin (masterdb) se han replicado en Subscriber (slavedb). Tampoco permite ninguna operación DML en el nodo Suscriptor:

slavedb=# select * from foo;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
(3 rows)

slavedb=# insert into foo values (4,'PG-Experts','Image2');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

Genial... Hemos movido los datos a una versión más nueva de PostgreSQL 9.3.5. En esta etapa, si cree que todos los datos se han replicado en el nodo de suscriptor, puede realizar el cambio.

3. Probando Switchover/Switchback.

Pasemos a la última versión con el script e intentemos insertar datos en los nodos de suscriptor/origen.

-bash-4.1$ slonik switchover.slonik
switchover.slonik:8: Set 1 has been moved from Node 1 to Node 2

slavedb=# insert into foo values (4,'PG-Experts','Image2');
INSERT 0 1

masterdb=# select * from foo ;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
4 | PG-Experts | Image2
(4 rows)

masterdb=# insert into foo values (5,'PG-Experts','Image3');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

Perfecto... Esto es lo que estamos buscando, ahora slavedb (Nodo de Suscriptor) ejecutando la versión PG 9.3.5 aceptando datos y masterdb (Nodo de Origen) recibiendo los datos de slavedb. También rechaza DML ejecutados en masterdb.

Slony-I Logs muestra los movimientos de identificación del nodo de origen/suscriptor en el momento de la conmutación:

2014-12-12 04:55:06 PST CONFIG moveSet: set_id=1 old_origin=1 new_origin=2
2014-12-12 04:55:06 PST CONFIG storeListen: li_origin=1 li_receiver=2 li_provider=1
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: update provider configuration
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: helper thread for provider 1 terminated
2014-12-12 04:55:06 PST CONFIG remoteWorkerThread_1: disconnecting from data provider 1
...
...
2014-12-12 04:55:11 PST INFO start processing ACCEPT_SET
2014-12-12 04:55:11 PST INFO ACCEPT: set=1
2014-12-12 04:55:11 PST INFO ACCEPT: old origin=1
2014-12-12 04:55:11 PST INFO ACCEPT: new origin=2
2014-12-12 04:55:11 PST INFO ACCEPT: move set seq=5000006393
2014-12-12 04:55:11 PST INFO got parms ACCEPT_SET

Si encuentra algún problema en esta etapa, puede volver a la versión anterior. Después de la reversión, puede continuar con la versión anterior hasta que su aplicación u otros problemas se solucionen. Este es el plan de reversión perfecto sin perder mucho tiempo en caso de problemas después del cambio.

-bash-4.1$ slonik switchback.slonik
switchback.slonik:8: Set 1 has been moved from Node 2 to Node 1

slavedb=# insert into foo values (5,'PG-Experts','Image3');
ERROR: Slony-I: Table foo is replicated and cannot be modified on a subscriber node - role=0

masterdb=# insert into foo values (5,'PG-Experts','Image3');
INSERT 0 1

slavedb=# select * from foo ;
id | name | image
----+----------------------+-------
1 | Raghav | test1
2 | Rao | test2
3 | Rags | test3
4 | PG-Experts | Image2
5 | PG-Experts | Image3
(5 rows)

Muy agradable…!!! ¿No es esta la reversión exacta con un tiempo de inactividad mínimo? Sí, es un cambio perfecto entre nodos sin perder una transacción.

Registros que muestran el cambio de suscriptor a nodo de origen:

2014-12-12 04:58:45 PST CONFIG moveSet: set_id=1 old_origin=2 new_origin=1
2014-12-12 04:58:45 PST CONFIG storeListen: li_origin=2 li_receiver=1 li_provider=2
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: update provider configuration
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: helper thread for provider 2 terminated
2014-12-12 04:58:45 PST CONFIG remoteWorkerThread_2: disconnecting from data provider 2
2014-12-12 04:58:46 PST CONFIG storeListen: li_origin=2 li_receiver=1 li_provider=2
...
...
2014-12-12 04:58:47 PST INFO start processing ACCEPT_SET
2014-12-12 04:58:47 PST INFO ACCEPT: set=1
2014-12-12 04:58:47 PST INFO ACCEPT: old origin=2
2014-12-12 04:58:47 PST INFO ACCEPT: new origin=1
2014-12-12 04:58:47 PST INFO ACCEPT: move set seq=5000006403
2014-12-12 04:58:47 PST INFO got parms ACCEPT_SET
2014-12-12 04:58:48 PST CONFIG moveSet: set_id=1 old_origin=2 new_origin=1

En este momento, es posible que haya notado que ninguna de las transacciones se pierde durante la operación de cambio entre las versiones de PostgreSQL. Solo el tiempo de inactividad puede ser su aplicación para iniciar/detener para conectarse a los nodos de origen y suscriptor, pero mientras que los nodos de origen/suscriptor nunca se eliminan, solo están en funcionamiento.

Recuerde, el método que se muestra aquí no solo es útil para actualizaciones, sino que es el mismo método en Slony-I para moverse entre nodos.

Gracias por su paciencia :). Espero que esta publicación lo ayude a actualizar PostgreSQL con un tiempo de inactividad mínimo utilizando Slony-I, incluido el plan de reversión adecuado.