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: