La extensión pglogical proporciona un flujo de replicación lógica para PostgreSQL, usando un módulo de publicación/suscripción. Se basa en una tecnología desarrollada como parte del Proyecto BDR .
Para describir los flujos de datos entre nodos, utilizamos los siguientes términos, reutilizados a partir de la anterior tecnología Slony:
- Nodos – Instancias de la base de datos PostgreSQL
- Proveedores y suscriptores – roles adoptados por los nodos
- Conjuntos de replicación – un conjunto de tablas
pglogical es una nueva tecnología que utiliza las últimas características in-core, de modo que existen las siguientes restricciones de versión:
- Los nodos proveedores y suscriptores deben ejecutar PostgreSQL 9.4 o superior
- Se requiere PostgreSQL 9.5 (o superior) para realizar filtros de origen de replicación y detectar conflictos.
- Además, el suscriptor puede ser Postgres-XL 9.5 o superior
Los casos de uso soportados son:
- Actualizaciones entre versiones principales (considerando las restricciones anteriores)
- Replicación completa de la base de datos
- Replicación selectiva de conjuntos de tablas utilizando series de replicación
- Replicación selectiva de filas de tablas tanto a nivel de editor como de suscriptor (row_filter)
- Replicación selectiva de columnas de la tabla a nivel de editor
- Recolección/fusión de los datos de múltiples servidores de subida
Detalles estructurales:
- pglogical funciona a nivel de base de datos, no a nivel de servidor integral como en un flujo de replicación física
- Un proveedor puede alimentar a varios suscriptores sin ocasionar una sobrecarga en la escritura del disco
- Un suscriptor puede fusionar cambios desde distintos orígenes. En caso de conflictos entre los mismos, logra solucionar de forma automática y configurable algunos de los aspectos requeridos para la replicación multi-maestro
- La replicación en cascada se implementa en forma de transmisión de conjuntos de cambios
1. Requisitos
Para usar pglogical el proveedor y el suscriptor deben estar ejecutando PostgreSQL 9.4 o superior.
La extensión pglogical
debe ser instalada tanto a nivel de proveedor como de suscriptor. Es necesario ejecutar CREATE EXTENSION pglogical
en ambos.
Las tablas en el proveedor y en el suscriptor deben presentar los mismos nombres y figurar en el mismo esquema. Futuras revisiones podrán añadir funciones de asignación.
Las tablas en el proveedor y en el suscriptor deben contener las mismas columnas, con los mismos tipos de datos en cada columna. Las restricciones CHECK
y NOT NULL
, etc. deben ser iguales o inferiores (más tolerantes) tanto para el suscriptor como para el proveedor.
Las tablas deben tener la misma PRIMARY KEY
. No se recomienda añadir más restricciones UNIQUE
aparte de la PRIMARY KEY
(véase más abajo).
En el apartado «Limitaciones y restricciones» que figura más abajo se presentan algunos requisitos adicionales.
2. Uso
En esta sección se describe el uso básico de la extensión de replicación pglogical.
2.1 Configuración rápida
Para empezar, el servidor PostgreSQL debe estar correctamente configurado para soportar la decodificación lógica:
wal_level = 'logical'
max_worker_processes = 10 # one per database needed on provider node
# one per node needed on subscriber node
max_replication_slots = 10 # one per node needed on provider node
max_wal_senders = 10 # one per node needed on provider node
shared_preload_libraries = 'pglogical'
Si está usando PostgreSQL 9.5 o superior (no funcionará con la versión 9.4) y quiere manejar la resolución de conflictos con last/first update wins (véase la sección «Conflictos» más abajo), puede añadir la siguiente opción a postgresql.conf:
track_commit_timestamp = on # needed for last/first update wins conflict resolution
# property available in PostgreSQL 9.5+
pg_hba.conf
debe permitir conexiones de replicación desde el localhost.
Luego, la extensión pglogical
tiene que ser instalada en todos los nodos:
CREATE EXTENSION pglogical;
Si está usando PostgreSQL 9.4, la extensión pglogical_origin
también tiene que ser instalada en ese nodo:
CREATE EXTENSION pglogical_origin;
Ahora cree el nodo proveedor:
SELECT pglogical.create_node(
node_name := 'provider1',
dsn := 'host=providerhost port=5432 dbname=db'
);
Añada todas las tablas del esquema public
al conjunto de replicación default
.
SELECT pglogical.replication_set_add_all_tables('default', ARRAY['public']);
Opcionalmente, puede crear conjuntos de replicación adicionales y añadirles tablas (véase la sección «Conjuntos de replicación» más abajo).
Generalmente, es mejor crear conjuntos de replicación antes del proceso de suscripción, de modo que durante la configuración inicial de la replicación todas las tablas estén sincronizadas en una única transacción. Sin embargo, los usuarios de bases de datos de mayor tamaño tal vez deseen crearlos de forma incremental para tener un mejor control.
Tras la configuración del nodo proveedor, los suscriptores podrán suscribirse al mismo. Pero primero deberá crearse el nodo suscriptor:
SELECT pglogical.create_node(
node_name := 'subscriber1',
dsn := 'host=thishost port=5432 dbname=db'
);
Finalmente, en el nodo suscriptor, podrá crear la suscripción que iniciará, en segundo plano, el proceso de sincronización y replicación:
SELECT pglogical.create_subscription(
subscription_name := 'subscription1',
provider_dsn := 'host=providerhost port=5432 dbname=db'
);
2.2 Administración de Nodos
Los nodos pueden ser agregados y removidos dinámicamente usando las interfaces SQL.
pglogical.create_node(node_name name, dsn text)
Crea un nodo. Parámetros:node_name
– nombre del nuevo nodo; sólo se permite un nodo por base de datosdsn
– cadena de conexión al nodo, para los nodos que se supone sean proveedores; debe ser accesible externamente
pglogical.drop_node(node_name name, ifexists bool)
Separa el nodo pglogical. Parámetros:node_name
– nombre de un nodo existenteifexists
– si es true, no se produce error si no existe suscripción; el valor predeterminado es false
pglogical.alter_node_add_interface(node_name name, interface_name name, dsn text)
Añade una interfaz adicional a un nodo. Cuando se crea un nodo, también se genera la interfaz correspondiente, cuyodsn
se especifica encreate_node
y lleva el mismo nombre del nodo. Esta interfaz permite añadir a un nodo existente interfaces alternativas con diferentes cadenas de conexión. Parámetros:node_name
– nombre de un nodo existenteinterface_name
– nombre de una nueva interfaz que se añadirádsn
– cadena de conexión al nodo utilizado para la nueva interfaz
pglogical.alter_node_drop_interface(node_name name, interface_name name)
Elimina la interfaz existente de un nodo. Parámetros:node_name
– nombre de un nodo existenteinterface_name
– nombre de una interfaz existente
2.3 Administración de suscripción
pglogical.create_subscription(subscription_name name, provider_dsn text, replication_sets text[], synchronize_structure boolean, synchronize_data boolean, forward_origins text[],
apply_delay interval
)
Crea una suscripción desde el nodo corriente hasta el nodo proveedor. El comando inicia la acción, no la interrumpe. Parámetros:subscription_name
– nombre de la suscripción, debe ser únicoprovider_dsn
– cadena de conexión a un proveedorreplication_sets
– matriz de conjuntos de replicación a las cuales suscribirse; deben ya haber sido creadas. El valor predeterminado es «{default,default_insert_only,ddl_sql}»synchronize_structure
– especifica si se debe sincronizar la estructura del proveedor con el suscriptor; el valor predeterminado es falsesynchronize_data
– especifica si se deben sincronizar los datos entre proveedor y suscriptor; el valor predeterminado es trueforward_origins
– matriz de nombres de origen a reenviar. Actualmente sólo los valores soportados son una matriz vacía, lo que significa que no reenvían ningún cambio que no se haya originado en el nodo proveedor, o «{all}» que significa replicar todos los cambios sin importar su origen, el valor predeterminado es «{all}»apply_delay
– indica la cantidad de retraso en la replicación; el valor predeterminado es 0 segundos
pglogical.drop_subscription(subscription_name name, ifexists bool)
Desconecta la suscripción y la elimina del catálogo. Parámetros:subscription_name
– nombre de la suscripción existenteifexists
– si es true, no se produce error si no existe suscripción; el valor predeterminado es false
pglogical.alter_subscription_disable(subscription_name name, immediate bool)
Deshabilita una suscripción y la desconecta del proveedor. Parámetros:subscription_name
– nombre de la suscripción existenteimmediate
– si es true, la suscripción se detendrá inmediatamente; de lo contrario sólo se detendrá al final de la transacción en curso; el valor predeterminado es false
pglogical.alter_subscription_enable(subscription_name name, immediate bool)
Habilita/deshabilita la suscripción. Parámetros:subscription_name
– nombre de la suscripción existenteimmediate
– si es true, la suscripción se iniciará inmediatamente, de lo contrario sólo se iniciará al final de la transacción en curso; el valor predeterminado es false
pglogical.alter_subscription_interface(subscription_name name, interface_name name)
Cambia la suscripción y utiliza una interfaz diferente para conectarse al nodo proveedor. Parámetros:subscription_name
– nombre de la suscripción existenteinterface_name
– nombre de una interfaz existente del actual nodo proveedor
pglogical.alter_subscription_synchronize(subscription_name name, truncate bool)
Las tablas no sincronizadas de todos los conjuntos se sincronizan en una sola operación. Se copian y sincronizan una por una. El comando inicia la acción, no la interrumpe. Parámetros:subscription_name
– nombre de la suscripción existentetruncate
-si es true, las tablas serán truncadas antes de la copia; el valor predeterminado es false
pglogical.alter_subscription_resynchronize_table(subscription_name name, relation regclass)
Resincroniza una tabla existente. ADVERTENCIA: Esta función truncará primero la tabla. Parámetros:subscription_name
– nombre de la suscripción existenterelation
– nombre de la tabla existente; opcionalmente calificable
pglogical.show_subscription_status(subscription_name name)
Muestra el estado y la información básica sobre la suscripción. Parámetros:subscription_name
– nombre opcional de la suscripción existente; si no se proporciona ningún nombre, la función mostrará el estado de todas las suscripciones del nodo local
pglogical.show_subscription_table(subscription_name name, relation regclass)
Muestra el estado de sincronización de una tabla. Parámetros:subscription_name
– nombre de la suscripción existenterelation
– nombre de la tabla existente; opcionalmente calificable
pglogical.alter_subscription_add_replication_set(subscription_name name, replication_set name)
Añade una serie de replicación a un suscriptor. No sincroniza, sólo activa el evento. Parámetros:subscription_name
-nombre de la suscripción existentereplication_set
– nombre del conjunto de replicación que se desea añadir
pglogical.alter_subscription_remove_replication_set(subscription_name name, replication_set name)
Elimina una serie de replicación de un suscriptor. Parámetros:subscription_name
– nombre de la suscripción existentereplication_set
– nombre del conjunto de replicación que se desea eliminar
2.4 Conjuntos de replicación
Los conjuntos de replicación proporcionan un mecanismo para controlar qué tablas de la base de datos y qué acciones de esas mismas tablas se replicarán.
Cada conjunto replicado puede especificar individualmente si las acciones INSERTs
, UPDATEs
, DELETEs
yTRUNCATEs
, presentes en el conjunto, se replicarán. Cada tabla puede encontrarse en múltiples conjuntos de replicación así como cada suscriptor puede suscribirse a múltiples conjuntos de replicación. El conjunto resultante de tablas y acciones replicadas es la unión de los conjuntos en los que se encuentra la tabla. Las tablas no se replican a menos que se añadan a un conjunto de replicación.
Hay tres conjuntos de replicación preexistentes llamados «default», «default_insert_only» y «ddl_sql». El conjunto de replicación «default» se define para replicar todos los cambios en las tablas introducidas. El «default_insert_only» sólo replica INSERTs y está destinado a las tablas que no tengan clave primaria (para más detalles, véase la sección Limitaciones). El conjunto de replicación «ddl_sql» se define para replicar los cambios de esquema especificados por pglogical.replicate_ddl_command
Para la gestión de los conjuntos de replicación se han previsto las siguientes funciones:
pglogical.create_replication_set(set_name name, replicate_insert bool, replicate_update bool, replicate_delete bool, replicate_truncate bool)
Esta función crea un nuevo conjunto de replicación. Parámetros:set_name
– nombre del conjunto; debe ser únicoreplicate_insert
– especifica siINSERT
se replica; el valor predeterminado es truereplicate_update
– especifica siUPDATE
se replica; el valor predeterminado es truereplicate_delete
– especifica siDELETE
se replica; el valor predeterminado es truereplicate_truncate
– especifica siTRUNCATE
se replica; el valor predeterminado es true
pglogical.alter_replication_set(set_name name, replicate_inserts bool, replicate_updates bool, replicate_deletes bool, replicate_truncate bool)
Esta función cambia los parámetros del conjunto de replicación existente. Parámetros:set_name
– nombre del conjunto de replicación existentereplicate_insert
– especifica siINSERT
se replica; el valor predeterminado es truereplicate_update
– especifica siUPDATE
se replica; el valor predeterminado es truereplicate_delete
– especifica siDELETE
se replica; el valor predeterminado es truereplicate_truncate
– especifica siTRUNCATE
se replica; el valor predeterminado es true
pglogical.drop_replication_set(set_name text)
Elimina el conjunto de replicación. Parámetros:set_name
– nombre del conjunto de replicación existente
pglogical.replication_set_add_table(set_name name, relation regclass, synchronize_data boolean,
columns text[], row_filter text)
Añade una tabla al conjunto de replicación. Parámetros:set_name
– nombre del conjunto de replicación existenterelation
– nombre u OID de la tabla que se añadirá al conjuntosynchronize_data
– Si es true, los datos de la tabla se sincronizan en todos los suscriptores de un determinado conjunto de replicación; el valor predeterminado es falsecolumns
– lista de columnas que deben ser replicadas. Normalmente, cuando todas las columnas deben ser replicadas, esto se establece en NULL, que es el valor predeterminadorow_filter
– Expresión de filtrado de filas; el valor predeterminado es NULL (ningún filtrado); para más información véase la sección Filtrado de filas. ADVERTENCIA: Tenga cuidado al sincronizar los datos con un filtro de fila válido. La operaciónsynchronize_data=true
con unrow_filter
válido se realiza una sola vez en una tabla. Ejecutarlo nuevamente con unrow_filter
modificado no sincronizará los datos con el suscriptor. Los suscriptores podrían necesitar ejecutarpglogical.alter_subscription_resynchronize_table()
para corregirlo.
pglogical.replication_set_add_all_tables(set_name name, schema_names text[], synchronize_data boolean)
Añade todas las tablas en los esquemas dados. Sólo se añaden las tablas existentes, las que se creen en el futuro no se añadirán automáticamente. Para saber cómo asegurar que las tablas creadas en el futuro se añadan al conjunto de replicación correcto, véase la sección Asignación automática de conjuntos de replicación para nuevas tablas. Parámetros:set_name
– nombre del conjunto de replicación existenteschema_names
– matriz de nombres de los esquemas existentes a partir de los cuales se deben añadir tablassynchronize_data
– si es true, los datos de la tabla se sincronizan en todos los suscriptores de un determinado conjunto de replicación; el valor predeterminado es false
pglogical.replication_set_remove_table(set_name name, relation regclass)
Elimina una tabla del conjunto de replicación. Parámetros:set_name
– nombre del conjunto de replicación existenterelation
– nombre u OID de la tabla que se eliminará del conjunto
pglogical.replication_set_add_sequence(set_name name, relation regclass, synchronize_data boolean)
Añade una secuencia al conjunto de replicación. Parámetros:set_name
– nombre del conjunto de replicación existenterelation
– nombre u OID de la secuencia que se añadirá al conjuntosynchronize_data
– si es true, el valor de la secuencia se sincronizará inmediatamente; el valor predeterminado es false
pglogical.replication_set_add_all_sequences(set_name name, schema_names text[], synchronize_data boolean)
Añade todas las secuencias en los esquemas dados. Sólo se añaden las secuencias existentes, las que se creen en el futuro no se añadirán automáticamente. Parámetros:set_name
– nombre del conjunto de replicación existenteschema_names
– matriz de nombres de los esquemas existentes a partir de los cuales deben añadirse secuenciassynchronize_data
– si es true, el valor de la secuencia se sincronizará inmediatamente; el valor predeterminado es false
pglogical.replication_set_remove_sequence(set_name name, relation regclass)
Elimina una tabla del conjunto de replicación. Parámetros:set_name
– nombre del conjunto de replicación existenterelation
– nombre u OID de la secuencia que se eliminará del conjunto
Puede averiguar la ubicación de cada tabla en los diferentes conjuntos mediante la opción pglogical.tables
.
2.4.1 Asignación automática de conjuntos de replicación para nuevas tablas
La función trigger puede utilizarse para describir las reglas que definen los conjuntos de replicación para las tablas recién creadas.
Ejemplo:
CREATE OR REPLACE FUNCTION pglogical_assign_repset() RETURNS event_trigger AS $$ DECLARE obj record; BEGIN FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() LOOP IF obj.object_type = 'table' THEN IF obj.schema_name = 'config' THEN PERFORM pglogical.replication_set_add_table('configuration', obj.objid); ELSIF NOT obj.in_extension THEN PERFORM pglogical.replication_set_add_table('default', obj.objid); END IF; END IF; END LOOP; END; $$ LANGUAGE plpgsql; CREATE EVENT TRIGGER pglogical_assign_repset_trg ON ddl_command_end WHEN TAG IN ('CREATE TABLE', 'CREATE TABLE AS') EXECUTE PROCEDURE pglogical_assign_repset();
En el ejemplo anterior, todas las nuevas tablas creadas en el esquema config
se pondrán en el configuration
del conjunto de replicación. Las demás tablas nuevas que no sean creadas por extensiones irán al conjunto de replicación default
.
2.5 Funciones adicionales
pglogical.replicate_ddl_command(command text, replication_sets text[])
Se ejecuta localmente y luego envia el comando especificado a la cola de replicación para su ejecución en los suscriptores de uno de losreplication_sets
. Parámetros:command
– Consulta DDL a ejecutarreplication_sets
– matriz de conjuntos de replicación con los que este comando debe asociarse; el valor predeterminado es «{ddl_sql}»
pglogical.synchronize_sequence(relation regclass)
Envía el estado de la secuencia a todos los suscriptores. A diferencia de la función de suscripción y sincronización de tablas, esta función debe ejecutarse en el proveedor. Fuerza la actualización del estado de la secuencia seguida. La misma podrá ser utilizada por todos los suscriptores, tras haber replicado la transacción en la que la función se ha ejecutado. El filtrado de conjuntos de replicación sigue siendo efectivo. Parámetros:relation
– nombre de la secuencia existente; opcionalmente calificable
2.6 Filtrado de filas
PGLogical permite el filtrado por filas tanto a nivel de proveedor como de suscriptor.
Filtrado de filas en el proveedor
A nivel de proveedor, el filtrado de filas puede realizarse especificando el parámetro row_filter
para la función pglogical.replication_set_add_table
. row_filter es una expresión de PostgreSQL que presenta las mismas limitaciones que la restricción CHECK
.
Un row_filter
sencillo sería algo parecido a row_filter := 'id > 0'
que permitiría la replicación únicamente de las filas en las que los valores de la columna id
sean superiores a cero.
Aunque se permite el uso de una función volátil dentro de row_filter
, hay que tener cuidado con las escrituras. De hecho, cualquier expresión que realice una escritura producirá un error y detendrá la replicación.
Vale la pena señalar también que row_filter
se ejecuta en la sesión de replicación. Por lo tanto, expresiones específicas de sesión como CURRENT_USER
tendrán los valores de la sesión de replicación y no de la sesión que realizó las escrituras.
Filtrado de filas en el suscriptor
A nivel de suscriptor, el filtrado de filas puede ser implementado usando el mecanismo estándar BEFORE TRIGGER
.
Es necesario invocar cualquiera de los triggers como ENABLE REPLICA
o ENABLE ALWAYS
, de lo contrario no serán ejecutados por el proceso de replicación.
3. Conflictos
En caso de que el nodo esté suscrito a varios proveedores, o cuando se produzcan escrituras locales en un suscriptor, pueden surgir conflictos debido a los cambios introducidos. Éstos se detectan automáticamente y pueden ser solucionados en función de la configuración.
La configuración para la resolución de conflictos se realiza a través de pglogical.conflict_resolution
. Los valores soportados para pglogical.conflict_resolution
son:
error
– Al detectarse un conflicto, la replicación se detendrá debido al error. Será necesaria una acción manual para resolverlo.apply_remote
– siempre aplica el cambio en conflicto con los datos locales; este es el valor predeterminadokeep_local
– mantiene la versión local de los datos e ignora el cambio conflictivo que proviene del nodo remotolast_update_wins
– se mantendrá la versión de los datos con la última marca de tiempo de confirmación (puede ser la versión local o la remota)first_update_wins
– se mantendrá la versión de los datos con la marca de tiempo más antigua (puede ser una versión local o remota)
La configuración disponible y los valores predeterminados dependen de la versión de PostgreSQL y de otros parámetros.
El valor predeterminado en PostgreSQL es apply_remote
.
Los parámetros keep_local
, last_update_wins
y first_update_wins
requieren que la configuración track_commit_timestamp
de PostgreSQL esté habilitada. Puesto que track_commit_timestamp
no está disponible en PostgreSQL 9.4 pglogical.conflict_resolution
solo puede ser apply_remote
o error
.
En Postgres-XL, el único valor soportado y el predeterminado es error
.
- pglogical.conflict_log_level Establece el nivel de registro para notificar los conflictos detectados cuando el
pglogical.conflict_resolution
está configurado para cualquier valor que no seaerror
. El principal empleo de esta configuración es eliminar el registro de conflictos. Los posibles valores son los mismos que para la configuración de PostgreSQLlog_min_messages
. El valor predeterminado esLOG
. - pglogical.batch_inserts Indica a PGLogical que, de ser posible, utilice el mecanismo interno de inserción por lotes de PostgreSQL, que es también utilizado por el comando
COPY
.Las inserciones por lotes mejoran el rendimiento de la replicación en las transacciones que realizan inserciones múltiples en una tabla. PGLogical pasará a la modalidad por lotes cuando la transacción haya realizado más de 5INSERT
. Sólo es posible pasar al modo por lotes cuando no existen triggersINSTEAD OF INSERT
yBEFORE INSERT
en la tabla y cuando no hay valores predeterminados con expresiones volátiles para las columnas de la tabla. Además, el modo por lotes sólo funcionará cuandopglogical.conflict_resolution
esté configurado comoerror
. El valor predeterminado estrue
. - pglogical.use_spi Indica a PGLogical que use la interfaz SPI, en lugar de usar la interfaz interna de bajo nivel, para generar sentencias SQL reales (
INSERT
,UPDATE
,DELETE
) con el fin de aplicar los cambios introducidos. Esto es útil principalmente para Postgres-XL y para fines de depuración. El valor predeterminado en PostgreSQL esfalse
. Esto puede ser configurado comotrue
sólo cuandopglogical.conflict_resolution
está configurado comoerror
. Este estado no permite detectar conflictos. En Postgres-XL la configuración predeterminada y únicamente permitida estrue
. - pglogical.temp_directory Define la ruta del sistema donde ubicar los archivos provisorios necesarios para la sincronización de los esquemas. La ruta debe existir y ser escribible por el usuario que ejecuta Postgres. El valor predeterminado es
empty
, lo cual indica a PGLogical que use el directorio temporal predefinido basado en la configuración del entorno y del sistema operativo.
4. Limitaciones y restricciones
4.1 Se requieren privilegios de superusuarios
Actualmente la replicación y gestión de pglogical requieren privilegios de superusuario. Posteriormente podrán extenderse a privilegios a nivel individual.
4.2 UNLOGGED
y TEMPORARY
no se replican
Las tablas UNLOGGED
y TEMPORARY
no serán y no podrán ser replicadas, como en el caso de un flujo de replicación física.
4.3 Una base de datos a la vez
Para replicar múltiples bases de datos es necesario establecer relaciones individuales proveedor/suscriptor para cada una de ellas. En una instalación PostgreSQL es imposible configurar al mismo tiempo la replicación de todas las bases de datos.
4.4 Se requieren PRIMARY KEY
o REPLICA IDENTITY
UPDATE
s y DELETE
s no pueden ser replicados en tablas que falten de PRIMARY KEY
u otra identidad de replicación válida como por ejemplo una restricción UNIQUE
. No existiendo un identificador único, la replicación no podrá determinar la tupla que debe ser actualizada o borrada.
Véase http://www.postgresql.org/docs/current/static/sql-altertable.html#SQL-CREATETABLE-REPLICA-IDENTITYhttp://www.postgresql.org/docs/current/static/sql-altertable.html#SQL-CREATETABLE-REPLICA-IDENTITY para detalles sobre la identidad de replicación.
4.5 Un sólo índice/restricción/PK UNIQUE
Si se configura más de un upstream, o si el downstream acepta escrituras locales, entonces en las tablas replicadas del downstream debería estar presente sólo un índice UNIQUE
. La resolución de conflictos sólo puede utilizar un índice a la vez; por lo que las filas en conflicto pueden producir ERROR
si una fila satisface la PRIMARY KEY
pero viola una restricción UNIQUE
a nivel de downstream. Esto detendrá la replicación hasta que en la tabla downstream se elimine la violación.
Es conveniente disponer de restricciones únicas adicionales en un upstream cuando el downstream sólo recibe escritos de dicho upstream. La regla es que las restricciones del downstream no deben ser más restrictivas que las de los upstream(s).
4.6 DDL
La replicación automática DDL no está soportada. La gestión del DDL para que la( s) base(s) de datos de proveedores y suscriptores siga(n) siendo compatible(s) es responsabilidad del usuario.
pglogical proporciona la función pglogical.replicate_ddl_command
para permitir que el DDL se ejecute en un punto coherente tanto en el proveedor como en el suscriptor.
4.7 La replicación del vaciado de cola no está soportada
La suspensión de las transacciones en el maestro y la espera de que todos los xacts en cola sean reproducidos desde las ranuras de implementación, no están soportadas. En una futura versión se añadirá el soporte para realizar el upstream de sólo lectura en el caso que se acaba de indicar.
Esto significa que hay que tener cuidado al momento de aplicar cambios en la estructura de la tabla. Si existen transacciones confirmadas que aún no se han replicado y la estructura de la tabla de proveedor y suscriptor se cambia al mismo tiempo en una manera que provoque la incompatibilidad de la tabla de suscriptores con las transacciones en cola, entonces se detendrá la replicación.
Antes de hacer cambios en el esquema, los administradores deben asegurarse de que se detengan las escrituras en el maestro. También pueden utilizar la función pglogical.replicate_ddl_command
para poner en cola los cambios en el esquema, de modo que se reproduzcan en un punto coherente de la replicación.
Una vez que se añada el soporte de replicación multi-maestro, el uso del comando pglogical.replicate_ddl_command
no será suficiente. Esto se debe a que, después de que el cambio de esquema se confirme en el editor, el suscriptor puede estar generando nuevos xacts con la estructura anterior. Por lo tanto, antes de realizar los cambios de esquema, los usuarios tendrán que asegurarse de que las escrituras se detengan en todos los nodos y de que todas las ranuras de implementación estén actualizadas.
4.8 CLAVES FORÁNEAS
Las restricciones de claves foráneas no se aplican al proceso de replicación. Lo que tiene éxito a nivel de proveedor se aplica también al suscriptor, incluso si FOREIGN KEY
fuese violada.
4.9 TRUNCATE
El uso de TRUNCATE ... CASCADE
sólo aplicará la opción CASCADE
a nivel de proveedor.
(Para el correcto uso de esta opción hará falta, probablemente, añadir el soporte ON TRUNCATE CASCADE
para las claves foráneas en PostgreSQL).
TRUNCATE ... RESTART IDENTITY
no está soportado. El proceso de reinicio de la identidad no es replicable en la replicación.
4.10 Secuencias
El estado de las secuencias añadidas a los conjuntos de replicación se replica periódicamente, no en tiempo real. Se utiliza un búfer dinámico para el valor que se está replicando, para que los suscriptores reciban efectivamente el estado futuro de la secuencia. Esto reduce la posibilidad (aunque no la elimina por completo) de que se retrase la noción del suscriptor en cuanto al last_value de la secuencia.
Podría ser conveniente utilizar la función synchronize_sequence
para asegurarse de que todos los suscriptores tengan información actualizada sobre una determinada secuencia después de eventos relevantes en la base de datos, como la carga de datos o durante la actualización en línea.
Generalmente se recomienda usar bigserial
y bigint
para las secuencias de los sistemas multi-nodos, ya que las secuencias de menor tamaño pueden alcanzar rápidamente el final del espacio requerido.
Los usuarios que deseen disponer de secuencias independientes en el proveedor y en el suscriptor pueden evitar añadirlas a los conjuntos de replicación. Crearán, en cambio, secuencias con un intervalo de pasos igual o mayor al número de nodos. Luego, establecerán un desfase diferente en cada nodo. Use la opción INCREMENT BY
para CREATE SEQUENCE
o ALTER SEQUENCE
, y use setval(...)
para definir el punto de inicio.
4.11 Triggers
Tanto el proceso de aplicación como el proceso inicial de COPY se ejecutan con session_replication_role
configurado en replica
. Esto significa que se activarán los triggers ENABLE REPLICA
y ENABLE ALWAYS
.
4.12 Diferencias de versión PostgreSQL
pglogical puede replicarse a través de las versiones principales de PostgreSQL. Sin embargo, la replicación a largo plazo entre versiones no se considera un objetivo del proyecto, aunque a menudo puede funcionar. Problemas de cambios que son válidos en el proveedor pero no en el suscriptor surgen con mayor frecuencia durante la replicación a través de las versiones.
Es más seguro replicar de una versión anterior a una más reciente ya que PostgreSQL mantiene una sólida compatibilidad con las versiones anteriores pero sólo una limitada con las versiones posteriores.
Replicar entre diferentes versiones menores no supone ninguna diferencia.
4.13 Diferencias de codificación en la base de datos
PGLogical no soporta la replicación entre bases de datos con diferente codificación. Recomendamos usar la codificación UTF-8
en todas las bases de datos replicadas.
4.14 No se replica el DDL
La decodificación lógica no decodifica directamente los cambios de catálogo. El plugin no puede enviar una declaración CREATE TABLE
cuando se añade una nueva tabla.
Si los datos decodificados se aplican a otra base de datos PostgreSQL, entonces sus definiciones de tablas deben mantenerse sincronizadas por algún medio externo al mismo plugin de decodificación lógica; como por ejemplo:
- Los eventos se activan usando la función deparse de DDL para capturar los cambios de DDL a medida que ocurren y escribirlos en una tabla. Luego serán replicados y aplicados en el otro extremo; o
- realizando la gestión del DDL mediante herramientas de sincronización DDL en todos los nodos
4.15 Postgres-XL
La versión mínima soportada de Postgres-XL es la 9.5r1.5.
Postgres-XL sólo está soportado como suscriptor (no como proveedor). En el caso de cargas de trabajo con numerosas transacciones pequeñas, el rendimiento de la replicación puede verse afectado por el aumento de la latencia de escritura. Por otra parte, las grandes transacciones de inserción (o de copia masiva) están fuertemente optimizadas para trabajar muy rápidamente con Postgres-XL.
También aplican las limitaciones DDL, por lo que hay que tener especial cuidado al usar replicate_ddl_command()
.
Postgre-XL cambia los valores predeterminados y los ajustes disponibles para las opciones de configuración pglogical.conflict_resolution
y pglogical.use_spi
.
5. ¿En qué difiere pglogical de BDR?
pglogical
se basa en una tecnología desarrollada para BDR con el cual comparte algunos códigos. Está diseñado para ser más flexible que BDR y para adaptarse con mayor facilidad a la replicación unidireccional de maestro único, recopilación/fusión de datos, topologías Non-MeSH multi-maestro, etc.
Carece de algunas características presentes en BDR:
- Malla multi-maestro. Aunque existe un soporte multi-maestro limitado para la resolución de conflictos, las conexiones de replicación mutua deben ser añadidas individualmente.
- Secuencias distribuidas. Usa diferentes desplazamientos de secuencias en cada nodo.
- Replicación DDL. Los usuarios mismos deben mantener definiciones de tablas consistentes. pglogical ayudará proporcionando funciones de cola.
- Bloqueo global DDL. Al no existir replicación DDL, no se requiere el bloqueo global… Aunque aplica únicamente a las tablas, eso genera problemas con la replicación mutua multi-maestro. Véase el siguiente punto.
- Vaciado global a un estado coherente. Parte del bloqueo DDL de BDR consiste en cerrar todas las colas de los nodos evitando que se produzcan nuevos xacts, para luego enviarlos a los nodos del mismo nivel. Esto asegura que no existan xacts, en la cola, que no puedan ser aplicados una vez que la estructura de la tabla haya cambiado. pglogical no lo hace, así que la replicación multi-maestro (en la que los nodos se replican entre sí) todavía no está soportada. Véase «Limitaciones».
Para más información, véase » Limitaciones y restricciones».
También añade algunas características:
- Conexiones flexibles entre nodos; la topología no está restringida a una configuración de malla como en el caso de BDR. La replicación lógica en cascada es posible.
- Plugin de salida sin conexión directa reutilizable para otros proyectos.
- Resultados en JSON para la inspección de las transacciones en cola
… su principal propósito es proporcionar una base más nítida y sencilla que no necesite un PostgreSQL parcheado, y que tenga un diseño acoplable y extensible.