47.2. Conceptos de decodificación lógica #

47.2.1. Decodificación lógica
47.2.2. Ranuras de replicación
47.2.3. Sincronización de ranuras de replicación
47.2.4. Plugins de salida
47.2.5. Instantáneas exportadas

47.2.1. Decodificación lógica #

La decodificación lógica es el proceso de extraer todos los cambios persistentes en las tablas de una base de datos en un formato coherente y fácil de entender que pueda interpretarse sin un conocimiento detallado del estado interno de la base de datos.

En PostgreSQL, la decodificación lógica se implementa decodificando el contenido del registro de escritura anticipada (write-ahead log), que describe los cambios a nivel de almacenamiento, en una forma específica de la aplicación, como un flujo de tuplas o sentencias SQL.

47.2.2. Ranuras de replicación #

En el contexto de la replicación lógica, una ranura (slot) representa un flujo de cambios que se pueden reproducir en un cliente en el orden en que se realizaron en el servidor de origen. Cada ranura transmite una secuencia de cambios desde una sola base de datos.

Note

PostgreSQL también tiene ranuras de replicación en flujo (consulta la Section 26.2.5), pero allí se utilizan de manera un poco diferente.

Una ranura de replicación tiene un identificador que es único en todas las bases de datos de un clúster de PostgreSQL. Las ranuras persisten independientemente de la conexión que las utilice y son seguras ante fallos.

Una ranura lógica emitirá cada cambio solo una vez en funcionamiento normal. La posición actual de cada ranura persiste solo en el checkpoint, por lo que en caso de una caída del servidor, la ranura podría volver a un LSN anterior, lo que hará que los cambios recientes se envíen de nuevo cuando el servidor se reinicie. Los clientes de decodificación lógica son responsables de evitar efectos no deseados al manejar el mismo mensaje más de una vez. Los clientes pueden desear registrar el último LSN que vieron al decodificar y omitir cualquier dato repetido o (cuando utilicen el protocolo de replicación) solicitar que la decodificación comience desde ese LSN en lugar de dejar que el servidor determine el punto de inicio. La función de seguimiento del progreso de la replicación está diseñada para este propósito, consulta los orígenes de replicación.

Pueden existir múltiples ranuras independientes para una sola base de datos. Cada ranura tiene su propio estado, lo que permite a diferentes consumidores recibir cambios desde diferentes puntos en el flujo de cambios de la base de datos. Para la mayoría de las aplicaciones, se requerirá una ranura independiente para cada consumidor.

Una ranura de replicación lógica no sabe nada sobre el estado del receptor o receptores. Incluso es posible tener múltiples receptores diferentes utilizando la misma ranura en diferentes momentos; simplemente obtendrán los cambios que sigan a partir del momento en que el último receptor dejó de consumirlos. Solo un receptor puede consumir cambios de una ranura en un momento dado.

También se puede crear una ranura de replicación lógica en un standby en caliente (hot standby). Para evitar que VACUUM elimine las filas necesarias de los catálogos del sistema, se debe establecer hot_standby_feedback en el standby. A pesar de eso, si se elimina alguna fila necesaria, la ranura se invalida. Se recomienda encarecidamente utilizar una ranura física entre el primario y el standby. De lo contrario, hot_standby_feedback funcionará pero solo mientras la conexión esté activa (por ejemplo, un reinicio del nodo la rompería). Entonces, el primario puede eliminar filas del catálogo del sistema que podrían ser necesarias para la decodificación lógica en el standby (ya que no conoce el catalog_xmin en el standby). Las ranuras lógicas existentes en el standby también se invalidan si el nivel de wal (wal_level) en el primario se reduce a menos de logical. Esto se hace tan pronto como el standby detecta dicho cambio en el flujo de WAL. Significa que, para los walsenders que están retrasados (si los hay), algunos registros de WAL hasta el cambio del parámetro wal_level en el primario no se decodificarán.

La creación de una ranura lógica requiere información sobre todas las transacciones actualmente en curso. En el primario, esta información está disponible directamente, pero en un standby, esta información debe obtenerse del primario. Por lo tanto, la creación de la ranura puede tener que esperar a que ocurra alguna actividad en el primario. Si el primario está inactivo, la creación de una ranura lógica en el standby puede llevar un tiempo notable. Esto se puede acelerar llamando a la función pg_log_standby_snapshot en el primario.

Caution

Las ranuras de replicación persisten a través de las caídas del servidor y no saben nada sobre el estado de su(s) consumidor(es). Evitarán la eliminación de los recursos necesarios incluso cuando no haya ninguna conexión que las utilice. Esto consume almacenamiento porque ni el WAL requerido ni las filas requeridas de los catálogos del sistema pueden ser eliminados por VACUUM mientras sean requeridos por una ranura de replicación. En casos extremos, esto podría causar el apagado de la base de datos para evitar el desbordamiento de ID de transacción (consulta la Section 24.1.5). Por lo tanto, si una ranura ya no es necesaria, debe eliminarse.

47.2.3. Sincronización de ranuras de replicación #

Las ranuras de replicación lógica en el primario se pueden sincronizar con el hot standby utilizando el parámetro failover de pg_create_logical_replication_slot, o utilizando la opción failover de CREATE SUBSCRIPTION durante la creación de la ranura. Además, se requiere habilitar sync_replication_slots en el standby. Al habilitar sync_replication_slots en el standby, las ranuras de failover se pueden sincronizar periódicamente en el trabajador slotsync. Para que la sincronización funcione, es obligatorio tener una ranura de replicación física entre el primario y el standby (es decir, primary_slot_name debe estar configurado en el standby), y hot_standby_feedback debe estar habilitado en el standby. También es necesario especificar un dbname válido en el primary_conninfo. Se recomienda encarecidamente que dicha ranura de replicación física se nombre en la lista synchronized_standby_slots en el primario, para evitar que el suscriptor consuma cambios más rápido que el hot standby. Incluso cuando está configurado correctamente, se espera cierta latencia al enviar cambios a los suscriptores lógicos debido a la espera en las ranuras nombradas en synchronized_standby_slots. Cuando se utiliza synchronized_standby_slots, el servidor primario no se apagará por completo hasta que los standbys correspondientes, asociados con las ranuras de replicación física especificadas en synchronized_standby_slots, hayan confirmado la recepción del WAL hasta la última posición purgada en el servidor primario.

Note

Si bien habilitar sync_replication_slots permite la sincronización periódica automática de las ranuras de failover, también se pueden sincronizar manualmente utilizando la función pg_sync_replication_slots en el standby. Sin embargo, esta función está destinada principalmente para pruebas y depuración y debe usarse con precaución. A diferencia de la sincronización automática, no incluye reintentos cíclicos, lo que la hace más propensa a fallos de sincronización, particularmente durante los escenarios de sincronización inicial donde los archivos WAL requeridos o las filas de catálogo para la ranura ya podrían haber sido eliminados o corren el riesgo de ser eliminados en el standby. En contraste, la sincronización automática a través de sync_replication_slots proporciona actualizaciones continuas de las ranuras, lo que permite un failover sin problemas y admite alta disponibilidad. Por lo tanto, es el método recomendado para sincronizar ranuras.

Cuando la sincronización de ranuras está configurada como se recomienda, y la sincronización inicial se realiza automáticamente o manualmente a través de pg_sync_replication_slots, el standby puede persistir la ranura sincronizada solo si se cumple la siguiente condición: La ranura de replicación lógica en el primario debe retener los WALs y las filas del catálogo del sistema que aún están disponibles en el standby. Esto garantiza la integridad de los datos y permite que la replicación lógica continúe sin problemas después de la promoción. Si los WALs o las filas del catálogo requeridos ya se han purgado del standby, la ranura no se persistirá para evitar la pérdida de datos. En tales casos, puede aparecer el siguiente mensaje de registro:

LOG:  could not synchronize replication slot "failover_slot"
DETAIL:  Synchronization could lead to data loss, because the remote slot needs WAL at LSN 0/3003F28 and catalog xmin 754, but the standby has LSN 0/3003F28 and catalog xmin 756.

Si la ranura de replicación lógica es utilizada activamente por un consumidor, no se necesita intervención manual; la ranura avanzará automáticamente y la sincronización se reanudará en el próximo ciclo. Sin embargo, si no hay ningún consumidor configurado, es aconsejable avanzar manualmente la ranura en el primario utilizando pg_logical_slot_get_changes o pg_logical_slot_get_binary_changes, permitiendo que proceda la sincronización.

La capacidad de reanudar la replicación lógica después del failover depende del valor de pg_replication_slots.synced para las ranuras sincronizadas en el standby en el momento del failover. Solo las ranuras persistentes que hayan alcanzado el estado de sincronización como verdadero en el standby antes del failover se pueden utilizar para la replicación lógica después del failover. Las ranuras sincronizadas temporales no se pueden utilizar para la decodificación lógica, por lo tanto, la replicación lógica para esas ranuras no se puede reanudar. Por ejemplo, si la ranura sincronizada no pudo volverse persistente en el standby debido a una suscripción deshabilitada, entonces la suscripción no se puede reanudar después del failover incluso cuando esté habilitada.

Para reanudar la replicación lógica después del failover desde las ranuras lógicas sincronizadas, el 'conninfo' de la suscripción debe modificarse para apuntar al nuevo servidor primario. Esto se hace utilizando ALTER SUBSCRIPTION ... CONNECTION. Se recomienda deshabilitar primero las suscripciones antes de promover el standby y volver a habilitarlas después de modificar la cadena de conexión.

Caution

Existe la posibilidad de que el antiguo primario vuelva a estar activo durante la promoción y, si las suscripciones no están deshabilitadas, los suscriptores lógicos pueden continuar recibiendo datos del antiguo servidor primario incluso después de la promoción hasta que se modifique la cadena de conexión. Esto podría dar lugar a problemas de inconsistencia de datos, evitando que los suscriptores lógicos puedan continuar la replicación desde el nuevo servidor primario.

47.2.4. Plugins de salida #

Los plugins de salida transforman los datos de la representación interna del registro de escritura anticipada al formato que desea el consumidor de una ranura de replicación.

47.2.5. Instantáneas exportadas #

Cuando se crea una nueva ranura de replicación utilizando la interfaz de replicación en flujo (consulta la CREATE_REPLICATION_SLOT), se exporta una instantánea (snapshot) (consulta la Section 9.28.5), que mostrará exactamente el estado de la base de datos a partir del cual se incluirán todos los cambios en el flujo de cambios. Esto se puede utilizar para crear una nueva réplica utilizando SET TRANSACTION SNAPSHOT para leer el estado de la base de datos en el momento en que se creó la ranura. Esta transacción se puede utilizar entonces para volcar el estado de la base de datos en ese momento, el cual posteriormente se puede actualizar utilizando el contenido de la ranura sin perder ningún cambio.

Las aplicaciones que no requieran la exportación de instantáneas pueden suprimirla con la opción SNAPSHOT 'nothing'.