Texto de decodificação lógica de commit de duas fases no PostgreSQL 14

Atualização: 2 de julho de 2023

Texto de decodificação lógica de commit de duas fases no PostgreSQL 14

A equipe de OSS da Fujitsu e a comunidade de código aberto PostgreSQL cooperaram para adicionar a função de descriptografar o commit de duas fases na replicação lógica no PG14. Vamos dar uma olhada no que é esse recurso?

fundo

O commit de duas fases é um mecanismo no qual as transações são confirmadas em duas fases. Normalmente usado em bancos de dados distribuídos para garantir a consistência. As duas fases da transação são a fase PREPARE e a fase COMMIT / ROLLBACK. Os comandos enviados em duas fases no PG são:

PREPARAR A TRANSAÇÃO

COMPROMETE-SE

ROLLBACK PREPARADO

PG já oferece suporte para confirmação de duas fases na versão 8.0 e a versão 10.0 oferece suporte para replicação lógica. No entanto, a confirmação de duas fases nunca foi suportada na replicação lógica. Os comandos PREPARE TRANSACTION, COMMIT PREPARED e ROLLBACK PREPARED têm suporte em uma única instância, mas quando esses comandos precisam ser copiados logicamente para a máquina em espera, eles não mantêm mais o significado original. O comando PREPARE TRANSACTION é tratado como NOP e não é decodificado. O comando COMMIT PREPARED é considerado como COMMIT e o comando ROLLBACK PREPARED é considerado como ABORT.

O que é um commit de duas fases

A confirmação de duas fases é um protocolo de confirmação atômica que ajuda a manter a consistência entre bancos de dados distribuídos. Os commits comuns que fornecem atomicidade no banco de dados não são suficientes para fornecer consistência para transações entre bancos de dados. Para ilustrar esse problema, vamos dar um exemplo:

1) John tem 300 $ no Banco A

2) Mark tem 100 $ no Banco B

3) John deseja transferir 100 $ para Mark

Durante a transação, você precisa sacar 100 $ do Banco A para o Banco B. No final da transação, deve haver 200 $. Se alguma transação falhar a qualquer momento durante o processo de transferência, o status da conta deve ser restaurado para o estado anterior ao início da transferência. A transação pode falhar por vários motivos. Se ocorrer alguma interrupção antes da confirmação da transação, a transação será revertida. Em nosso exemplo, se ocorrer uma interrupção quando a conta de John for deduzida, a conta de John da porta de interrupção não deve ser reduzida. É assim que uma confirmação simples mantém a consistência no banco de dados.

Mas consideramos tal situação, ou seja, a transação que deduz 100 $ da conta de João é bem-sucedida em um envio, mas a transação que adiciona $ 100 à conta de Marcos no Banco B falha e é revertida. Após o término dessa operação, embora a conta de João tenha sido debitada, Marcos não receberá a quantia. 100 $ desapareceram. Ao lidar com transações distribuídas, uma confirmação simples pode falhar.

Execução passo a passo de transações distribuídas

Para o two-phase commit, um dos bancos de dados atua como coordenador de transações distribuídas.

Estágio 1

Um banco de dados começa a aplicar as transações e, a seguir, a se preparar. Ele envia transações preparadas para outros bancos de dados na forma de mensagens de preparação. O segundo banco de dados obtém a mensagem Prepare e, em seguida, prepara a transação. Preparar envolve mudanças na transação, mas não se compromete. Os dados sujos são gravados no disco para persistência. Depois que todos os bancos de dados prepararam a transação e todas as informações sobre a transação foram armazenadas em disco, a fase de preparação está concluída.

Estágio 2

Em seguida, o árbitro inicia a fase de confirmação. Se o segundo banco de dados falhar em preparar a transação por algum motivo, o árbitro iniciará a fase de reversão. Portanto, dependendo se a preparação foi bem-sucedida, a transação é confirmada ou revertida. A interrupção na fase final de confirmação pode ser recuperada, porque a transação de preparação necessária foi gravada no disco e pode ser reaplicada.

A confirmação de duas fases não está relacionada a bancos de dados de instância única, mas é relevante quando os dados são replicados em várias instâncias de banco de dados.

É muito importante oferecer suporte à confirmação de duas fases na replicação lógica.

Visão Geral Funcional

Antes da versão PG14, as transações de replicação lógica eram decodificadas e replicadas somente após a confirmação da transação. Isso evita que a transação de replicação seja abortada.

Decodificar a transação na confirmação

A replicação lógica de PG14 suporta os comandos PREPARE TRANSACTION, COMMIT PREPARED e ROOLBACK PREPARED. Quando o comando PREPARE TRANSACTION é decodificado, a transação é decodificada e copiada. PREPARE TRANSACTION inicia a reprodução e decodificação da transação exatamente como o COMMIT no WAL SENDER.

Transação de decodificação durante a preparação

Também definimos um novo retorno de chamada de plug-in para permitir que os plug-ins de decodificação lógica suportem o envio em duas fases.

Callback

descreve

filtrar_preparar_cb

Permite que o plugin filtre transações que não precisam ser decodificadas ao preparar de acordo com o GID usado no comando PREPARE TRANSACTION

começar_preparar_cb

Início da transação de preparação

preparar_cb

Chamado quando o comando PREPARE TRANSACTION é decodificado

commit_preparado_cb

Chamado quando o comando COMMIT PREPARED é decodificado

rollback_preparado_cb

Chamado quando o comando ROLLBACK PREPARED é decodificado

Modificação de plug-in

teste_decodificação

O plug-in é um plug-in de saída de decodificação lógica, como um exemplo para ajudar os usuários a desenvolver seu próprio plug-in de decodificação lógico. test_decoding recebe WAL por meio de um mecanismo lógico de decodificação e o decodifica em uma representação textual da operação realizada.

Ele foi modificado para ser capaz de usar a nova função de retorno de chamada de dois estágios e decodificar a transação durante a preparação

Modificação de APIs

pg_create_logical_replication_slot ()

A API adiciona uma nova opção para especificar se o slot oferece suporte para confirmação de duas fases. O plug-in de saída pode usar um slot de replicação com uma opção de duas fases para suportar o commit de duas fases.

pg_criar_replicação_lógica_slot (nome_nome do slot, nome do plugin [, booleano temporário, booleano de duas fases])

Estudo de caso

Vamos ver como detectar a saída decodificada da transação two-phase commit:

1) Crie um slot de replicação

Use test_decoding como o plug-in de saída e transmita true para que o slot suporte o envio e a decodificação em dois estágios.

postgres, SELECT, FROM pg_create_logical_replication_slot ('regression_slot', 'test_decoding', false, true).

slot_name | lsn

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

regressão_lot | 0 / 16B1970

(1 linha)

2) Crie uma mesa

postgres = # CREATE TABLE data (chave serial primária id, texto de dados) ;

CRIAR TABELA

3) Detectar o conteúdo de saída decodificado da transação de preparação e confirmação da transação

postgres = # BEGIN ;

postgres = * # INSERT INTO data (data) VALUES ('5') ;

postgres = * # PREPARE TRANSACTION 'test_prepared1' ;

postgres, SELECT, FROM pg_logical_slot_get_changes, regression_slot, NULL, NULL e

dados lsn | xid |

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

0 / 1689DC0 | 529 | BEGIN 529

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

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

(3 linhas)

postgres = # COMMIT PREPARED 'test_prepared1' ;

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

dados lsn | xid |

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

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

(4 linhas)

postgres = # select * from data ;

id | dados

---- + ------

1 | 5

(1 linha)

futuro

A alteração do PG14 para esta função tem uma infraestrutura do lado do decodificador que permite o envio de decodificação em dois estágios durante a preparação. Também modificamos o plug-in test_decoding para aproveitar as vantagens dessa infraestrutura.

A próxima etapa é implementar o suporte de dois estágios para o maior plug-in de decodificação lógica no PG-o plug-in pgoutput. Este plug-in suporta o modo PUBLISHER / ASSINANTE de replicação lógica. É o plug-in mais usado em replicação lógica. A equipe de OSS da Fujitsu está trabalhando com a comunidade de código aberto para adicionar esse recurso ao PG15.

Para a transação de duas fases no banco de dados distribuído, PG também precisa oferecer suporte: a máquina em espera informa ao host que PREPARE falhou e inicia um rollback. Este mecanismo de feedback não é suportado no PG e é uma das direções para melhorias futuras.

  Links:

6mbi25l-120

rm500uz-2h