Testo di decodifica logica del commit a due fasi in PostgreSQL 14

Aggiornamento: 2 luglio 2023

Testo di decodifica logica del commit a due fasi in PostgreSQL 14

Il team Fujitsu OSS e la comunità open source PostgreSQL hanno collaborato per aggiungere la funzione di decrittografia del commit a due fasi nella replica logica in PG14. Diamo un'occhiata a cosa è questa caratteristica?

sfondo

Il commit a due fasi è un meccanismo in cui le transazioni vengono impegnate in due fasi. Solitamente utilizzato nei database distribuiti per garantire la coerenza. Le due fasi della transazione sono la fase PREPARE e la fase COMMIT/ROLLBACK. I comandi inviati in due fasi in PG sono:

PREPARA LA TRANSAZIONE

IMPEGNO PREPARATO

ROLLBACK PREPARATO

PG supporta già il commit in due fasi nella versione 8.0 e la versione 10.0 supporta la replica logica. Tuttavia, il commit in due fasi non è mai stato supportato nella replica logica. I comandi PREPARE TRANSACTION, COMMIT PREPARED e ROLLBACK PREPARED sono stati supportati in un'unica istanza, ma quando questi comandi devono essere copiati logicamente sulla macchina in standby, non mantengono più il significato originale. Il comando PREPARE TRANSACTION viene trattato come un NOP e non viene decodificato affatto. Il comando COMMIT PREPARED è considerato COMMIT e il comando ROLLBACK PREPARED è considerato ABORT.

Che cos'è un commit in due fasi?

Il commit a due fasi è un protocollo di commit atomico che aiuta a mantenere la coerenza tra i database distribuiti. I commit ordinari che forniscono atomicità all'interno del database non sono sufficienti per fornire coerenza per le transazioni tra database. Per illustrare questo problema, diamo un esempio:

1) John ha 300$ in banca A

2) Mark ha 100$ nel banco B

3) John vuole trasferire 100$ a Mark

Durante la transazione, devi prelevare 100$ dalla Banca A alla Banca B. Alla fine della transazione, dovrebbero esserci 200$. Se una transazione fallisce in qualsiasi momento durante il processo di trasferimento, lo stato dell'account deve essere ripristinato allo stato prima dell'inizio del trasferimento. La transazione potrebbe fallire per vari motivi. Se si verifica un'interruzione prima del commit della transazione, verrà eseguito il rollback della transazione. Nel nostro esempio, se si verifica un'interruzione quando viene detratto il conto di John, il conto di John della porta di interruzione non deve essere ridotto. Questo è il modo in cui un semplice commit mantiene la coerenza all'interno del database.

Ma consideriamo una situazione del genere, ovvero, la transazione che sottrae 100 $ dal conto di John ha successo in un invio, ma la transazione che aggiunge 100 $ al conto di Mark nella banca B fallisce e viene annullata. Al termine di questa operazione, nonostante l'addebito sul conto di John sia stato effettuato, Mark non riceverà l'importo. 100 $ scomparsi. Quando si tratta di transazioni distribuite, un semplice commit potrebbe non riuscire.

Esecuzione passo passo di transazioni distribuite

Per il commit a due fasi, uno dei database funge da coordinatore delle transazioni distribuite.

Stage 1

Un database inizia ad applicare le transazioni e quindi a prepararsi. Invia le transazioni preparate ad altri database sotto forma di messaggi di preparazione. Il secondo database riceve il messaggio Prepare e quindi prepara la transazione. Preparare comporta modifiche nella transazione, ma non si impegna. I dati sporchi vengono scritti su disco per la persistenza. Una volta che tutti i database hanno preparato la transazione e tutte le informazioni sulla transazione sono state archiviate su disco, la fase di preparazione è completa.

Stage 2

Successivamente, l'arbitro inizia la fase di commit. Se il secondo database non riesce a preparare la transazione per qualche motivo, l'arbitro avvia la fase di rollback. Pertanto, a seconda che la preparazione abbia esito positivo, viene eseguito il commit o il rollback della transazione. L'interruzione nella fase di commit finale può essere recuperata, poiché la transazione di preparazione richiesta è stata scritta su disco e può essere riapplicata.

Il commit in due fasi non è correlato ai database a istanza singola, ma è rilevante quando i dati vengono replicati su più istanze di database.

È molto importante supportare il commit in due fasi nella replica logica.

Panoramica funzionale

Prima della versione PG14, le transazioni di replica logica venivano decodificate e replicate solo dopo il commit della transazione. Questo per evitare che la transazione di replica possa essere interrotta.

Decodifica transazione su commit

La replica logica di PG14 supporta i comandi PREPARE TRANSACTION, COMMIT PREPARED e ROOLBACK PREPARED. Quando viene decodificato il comando PREPARE TRANSACTION, la transazione viene decodificata e copiata. PREPARE TRANSACTION avvia la riproduzione e la decodifica della transazione proprio come COMMIT in WAL SENDER.

Transazione di decodifica durante la preparazione

Abbiamo anche definito un nuovo callback del plug-in per consentire ai plug-in di decodifica logica di supportare l'invio in due fasi.

Richiamata

descrivere

filtrare_preparare_cb

Consenti al plugin di filtrare le transazioni che non devono essere decodificate durante la preparazione in base al GID utilizzato nel comando PREPARE TRANSACTION

iniziare_preparare_cb

Inizio della preparazione della transazione

preparare_cb

Chiamato quando viene decodificato il comando PREPARE TRANSACTION

commit_preparato_cb

Chiamato quando viene decodificato il comando COMMIT PREPARED

rollback_preparato_cb

Chiamato quando viene decodificato il comando ROLLBACK PREPARED

Modifica plug-in

prova_decodifica

Il plug-in è un plug-in di output di decodifica logica, ad esempio per aiutare gli utenti a sviluppare il proprio plug-in di decodifica logica. test_decoding riceve WAL attraverso un meccanismo di decodifica logica e lo decodifica in una rappresentazione testuale dell'operazione eseguita.

È stato modificato per poter utilizzare la nuova funzione di callback a due fasi e decodificare la transazione durante la preparazione

Modifica delle API

pg_creare_slot_di replicazione logica()

L'API aggiunge una nuova opzione per specificare se lo slot supporta il commit a due fasi. Il plug-in di output può utilizzare uno slot di replica con un'opzione a due fasi per supportare il commit a due fasi.

pg_create_logical_replication_slot(slot_nome nome, nome plugin [, booleano temporaneo, booleano a due fasi ] )

Caso di studio

Vediamo come rilevare l'output decodificato della transazione di commit a due fasi:

1) Creare uno slot di replica

Usa test_decoding come plug-in di output e passa true in modo che lo slot supporti l'invio e la decodifica in due fasi.

postgres=# SELECT * FROM pg_creaslot_di_replica_logica_slot_regressione', 'test_decoding', false, true);

slot_nome | lsn

io

regressione_slot | 0/16B1970

1 riga)

2) Crea una tabella

postgres=# CREATE TABLE data(id seriale chiave primaria, testo dati);

CREA TABELLA

3) Rilevare il contenuto dell'output decodificato della transazione di preparazione e commit della transazione

postgres=# INIZIO;

postgres=*# INSERISCI IN data(data) VALORI('5');

postgres=*# PREPARA TRANSAZIONE test_preparato1';

postgres=# SELECT * FROM pg_slot_logico_get_changes('regressionslot', NULL, NULL);

lsn | xid | dati

io

0/1689DC0 | 529 | INIZIO 529

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

0/1689FC0 | 529 | PREPARA TRANSAZIONE 'test_preparato1', txid 529

3 righe)

postgres=# COMMIT PREPARATO test_preparato1';

postgres=# seleziona * da pg_logico_slot_get_changes('regression_slot', NULL, NULL);

lsn | xid | dati

io

0/168A060 | 529 | COMMIT PREPARATO test_preparato1', txid 529

4 righe)

postgres=# seleziona *dai dati;

ID dati

io

1 | 5

1 riga)

futuro

La modifica di PG14 a questa funzione ha un'infrastruttura lato decoder che consente l'invio della decodifica in due fasi durante la preparazione. Abbiamo anche modificato il plugin test_decoding per sfruttare questa infrastruttura.

Il prossimo passo è implementare il supporto in due fasi al più grande plug-in di decodifica logica in PG, il plug-in pgoutput. Questo plug-in supporta la modalità di replica logica PUBLISHER/SUBSCRIBER. È il plug-in più utilizzato nella replica logica. Il team Fujitsu OSS sta lavorando con la comunità open source per aggiungere questa funzionalità a PG15.

Per la transazione in due fasi nel database distribuito, anche PG deve supportare: la macchina in standby informa l'host che PREPARE non è riuscita e avvia un rollback. Questo meccanismo di feedback non è supportato in PG ed è una delle direzioni per miglioramenti futuri.

  Collegamento:

6mbi25l-120

rm500uz-2 ore