Texto de decodificación lógica de la confirmación de dos fases en PostgreSQL 14

Actualización: 2 de julio de 2023

Texto de decodificación lógica de la confirmación de dos fases en PostgreSQL 14

El equipo de Fujitsu OSS y la comunidad de código abierto de PostgreSQL han cooperado para agregar la función de descifrar la confirmación de dos fases en la replicación lógica en PG14. Echemos un vistazo a lo que es esta característica.

fondo

La confirmación de dos fases es un mecanismo en el que las transacciones se comprometen en dos fases. Normalmente se utiliza en bases de datos distribuidas para garantizar la coherencia. Las dos fases de la transacción son la fase PREPARE y la fase COMMIT / ROLLBACK. Los comandos enviados en dos fases en PG son:

PREPARAR LA TRANSACCIÓN

COMPROMISO PREPARADO

ROLLBACK PREPARADO

PG ya admite la confirmación en dos fases en la versión 8.0 y la versión 10.0 admite la replicación lógica. Sin embargo, la confirmación en dos fases nunca ha sido compatible con la replicación lógica. Los comandos PREPARE TRANSACTION, COMMIT PREPARED y ROLLBACK PREPARED se han admitido en una sola instancia, pero cuando estos comandos deben copiarse lógicamente en la máquina en espera, ya no mantienen el significado original. El comando PREPARE TRANSACTION se trata como un NOP y no se decodifica en absoluto. El comando COMMIT PREPARED se considera COMMIT y el comando ROLLBACK PREPARED se considera ABORT.

¿Qué es un compromiso de dos fases?

La confirmación de dos fases es un protocolo de confirmación atómico que ayuda a mantener la coherencia entre las bases de datos distribuidas. Las confirmaciones ordinarias que proporcionan atomicidad dentro de la base de datos no son suficientes para proporcionar consistencia para las transacciones entre bases de datos. Para ilustrar este problema, demos un ejemplo:

1) John tiene 300 $ en el Banco A

2) Mark tiene 100 $ en el Banco B

3) John quiere transferir 100 $ a Mark

Durante la transacción, debe retirar 100 $ del Banco A al Banco B. Al final de la transacción, debe haber 200 $. Si alguna transacción falla en cualquier momento durante el proceso de transferencia, el estado de la cuenta debe restablecerse al estado anterior al inicio de la transferencia. La transacción puede fallar por varias razones. Si se produce alguna interrupción antes de que se confirme la transacción, la transacción se revertirá. En nuestro ejemplo, si ocurre una interrupción cuando se deduce la cuenta de John, entonces la cuenta de John del puerto de interrupción no debe reducirse. Así es como una confirmación simple mantiene la coherencia dentro de la base de datos.

Pero consideramos tal situación, es decir, la transacción que deduce 100 $ de la cuenta de John tiene éxito en una presentación, pero la transacción que agrega 100 $ a la cuenta de Mark en el Banco B falla y se revierte. Una vez finalizada esta operación, aunque se ha debitado la cuenta de John, Mark no recibirá la cantidad. 100 $ desaparecieron. Cuando se trata de transacciones distribuidas, una confirmación simple puede fallar.

Ejecución paso a paso de transacciones distribuidas

Para el compromiso de dos fases, una de las bases de datos actúa como coordinador de transacciones distribuidas.

1

Una base de datos comienza a aplicar transacciones y luego se prepara. Envía transacciones preparadas a otras bases de datos en forma de preparar mensajes. La segunda base de datos recibe el mensaje Preparar y luego prepara la transacción. Preparar implica cambios en la transacción, pero no se compromete. Los datos sucios se escriben en el disco para su persistencia. Una vez que todas las bases de datos han preparado la transacción y toda la información sobre la transacción se almacena en el disco, la fase de preparación se completa.

2

A continuación, el árbitro inicia la fase de compromiso. Si la segunda base de datos no puede preparar la transacción por algún motivo, el árbitro inicia la fase de reversión. Por lo tanto, dependiendo de si la preparación es correcta, la transacción se confirma o se revierte. La interrupción en la fase de confirmación final se puede recuperar, porque la transacción de preparación requerida se ha escrito en el disco y se puede volver a aplicar.

La confirmación en dos fases no está relacionada con las bases de datos de una sola instancia, pero es relevante cuando los datos se replican en varias instancias de la base de datos.

Es muy importante admitir el compromiso de dos fases en la replicación lógica.

Descripción funcional

Antes de la versión PG14, las transacciones de replicación lógica se decodificaban y replicaban solo después de que se confirmaba la transacción. Esto es para evitar que la transacción de replicación eventualmente se anule.

Decodificar la transacción en el compromiso

La replicación lógica de PG14 admite los comandos PREPARE TRANSACTION, COMMIT PREPARED y ROOLBACK PREPARED. Cuando se decodifica el comando PREPARE TRANSACTION, la transacción se decodifica y copia. PREPARE TRANSACTION inicia la reproducción y decodificación de la transacción como COMMIT en WAL SENDER.

Decodificación de la transacción durante la preparación

También definimos una nueva devolución de llamada de complemento para permitir que los complementos de decodificación lógica admitan el envío en dos fases.

Devolución de llamada

describir

filtrar_preparar_cb

Permita que el complemento filtre las transacciones que no necesitan ser decodificadas cuando se preparan de acuerdo con el GID usado en el comando PREPARE TRANSACTION

empezar_preparar_cb

Inicio de la transacción de preparación

preparar_cb

Se llama cuando se decodifica el comando PREPARE TRANSACTION

cometer_preparado_cb

Se llama cuando se decodifica el comando COMMIT PREPARED

retroceder_preparado_cb

Se llama cuando se decodifica el comando ROLLBACK PREPARED

Modificación de complemento

prueba_descodificación

El complemento es un complemento de salida de decodificación lógica, como ejemplo para ayudar a los usuarios a desarrollar su propio complemento de decodificación lógica. test_decoding recibe WAL a través de un mecanismo de decodificación lógica y lo decodifica en una representación textual de la operación realizada.

Se ha modificado para poder utilizar la nueva función de devolución de llamada de dos etapas y decodificar la transacción durante la preparación.

Modificación de API

pg_crear_replicación_lógica_slot ()

La API agrega una nueva opción para especificar si la ranura admite el compromiso de dos fases. El complemento de salida puede usar una ranura de replicación con una opción de dos fases para admitir el compromiso de dos fases.

pg_create_replicationslot (slot_name nombre, nombre del complemento ,, booleano temporal, booleano de dos fases])

Estudio de caso

Veamos cómo detectar la salida decodificada de la transacción de confirmación de dos fases:

1) Cree una ranura de replicación

Use test_decoding como el complemento de salida y pase verdadero para que la ranura admita el envío y la decodificación en dos etapas.

postgres = # SELECT * FROM pg_create_replicationlogical_slot ('regression_slot , ,' test_decoding ', false , true) ;

slot_name | lsn

----------------- + -----------

regression_slot | 0 / 16B1970

(1 fila)

2) Crea una tabla

postgres = # CREATE TABLE data (id clave serial primaria , texto de datos) ;

Crear mesa

3) Detectar el contenido de salida decodificado de preparar la transacción y confirmar la transacción

postgres = # BEGIN ;

postgres = * # INSERT INTO datos (datos) VALORES ('5') ;

postgres = * # PREPARE TRANSACTION 'test_prepared1' ;

postgres = # SELECT * FROM pg_logical_slot_get_changes ('regression_slot' , NULL , NULL) ;

lsn | xid | datos

----------- + ----- + -----------------

0 / 1689DC 0 | 529 | COMIENZO 529

0 / 1689DC0 | 529 | tabla public.data : INSERT : id [integer] : 3 data [text] : '5'

0 / 1689FC0 | 529 | PREPARE TRANSACTION 'test_prepared1' , txid 529

(3 filas)

postgres = # COMMIT PREPARED 'test_prepared1' ;

postgres = # select * from pg_logical_slot_get_changes ('regression_slot' , NULL , NULL) ;

lsn | xid | datos

----------- + ----- + ------------------

0 / 168A060 | 529 | COMMIT PREPARED 'test_prepared1' , txid 529

(4 filas)

postgres = # seleccionar * de datos ;

id | datos

---- + ------

1 | 5

(1 fila)

futuras

El cambio de PG14 a esta función tiene una infraestructura del lado del decodificador que permite el envío de la decodificación en dos etapas durante la preparación. También modificamos el complemento test_decoding para aprovechar esta infraestructura.

El siguiente paso es implementar el soporte de dos etapas para el complemento de decodificación lógica más grande en PG, el complemento pgoutput. Este complemento admite el modo de replicación lógica PUBLISHER / SUBSCRIBER. Es el complemento más utilizado en la replicación lógica. El equipo de Fujitsu OSS está trabajando con la comunidad de código abierto para agregar esta función a PG15.

Para la transacción de dos fases en la base de datos distribuida, PG también necesita ser compatible: la máquina en espera informa al host que PREPARE ha fallado e inicia una reversión. Este mecanismo de retroalimentación no es compatible con PG y es una de las direcciones para futuras mejoras.

  enlaces:

6mbi25l-120

rm500uz-2h