Logische decoderingstekst van commit in twee fasen in PostgreSQL 14

Update: 2 juli 2023

Logische decoderingstekst van commit in twee fasen in PostgreSQL 14

Het Fujitsu OSS-team en de PostgreSQL-open source-gemeenschap hebben samengewerkt om de functie van het decoderen van de tweefasige commit in logische replicatie in PG14 toe te voegen. Laten we eens kijken naar wat deze functie is?

achtergrond

Two-phase commit is een mechanisme waarbij transacties in twee fasen worden vastgelegd. Meestal gebruikt in gedistribueerde databases om consistentie te garanderen. De twee fasen van de transactie zijn de PREPARE-fase en de COMMIT/ROLLBACK-fase. De opdrachten die in twee fasen in PG worden ingediend, zijn:

TRANSACTIE VOORBEREIDEN

COMMIT BEREID

ROLLBACK VOORBEREID

PG ondersteunt al tweefasige commits in versie 8.0, en versie 10.0 ondersteunt logische replicatie. Vastlegging in twee fasen is echter nooit ondersteund bij logische replicatie. De opdrachten PREPARE TRANSACTION, COMMIT PREPARED en ROLLBACK PREPARED zijn in één exemplaar ondersteund, maar wanneer deze opdrachten logisch naar de standby-machine moeten worden gekopieerd, behouden ze niet langer de oorspronkelijke betekenis. Het PREPARE TRANSACTION-commando wordt behandeld als een NOP en wordt helemaal niet gedecodeerd. Het COMMIT PREPARED-commando wordt beschouwd als COMMIT, en het ROLLBACK PREPARED-commando wordt beschouwd als ABORT.

Wat is een commit in twee fasen?

Commit in twee fasen is een atomair commit-protocol dat helpt om de consistentie tussen gedistribueerde databases te behouden. Gewone commits die atomiciteit binnen de database bieden, zijn niet voldoende om consistentie te bieden voor transacties tussen databases. Laten we een voorbeeld geven om dit probleem te illustreren:

1) John heeft $ 300 in Bank A

2) Mark heeft 100$ in Bank B

3) John wil 100 $ overmaken naar Mark

Tijdens de transactie moet u $ 100 opnemen van bank A naar bank B. Aan het einde van de transactie moet er $ 200 zijn. Als een transactie op enig moment tijdens het overboekingsproces mislukt, moet de accountstatus worden hersteld naar de status voordat de overboeking begon. De transactie kan om verschillende redenen mislukken. Als er een onderbreking optreedt voordat de transactie wordt vastgelegd, wordt de transactie teruggedraaid. Als in ons voorbeeld een onderbreking optreedt wanneer de rekening van John wordt afgeschreven, moet de rekening van John van de onderbrekingspoort niet worden verlaagd. Dit is hoe een eenvoudige commit de consistentie binnen de database handhaaft.

Maar we beschouwen een dergelijke situatie, dat wil zeggen dat de transactie waarbij 100$ wordt afgetrokken van de rekening van John in één keer succesvol is, maar de transactie die 100$ toevoegt aan de rekening van Mark bij Bank B mislukt en wordt teruggedraaid. Nadat deze operatie voorbij is, zal Mark het bedrag niet ontvangen, hoewel John's rekening is afgeschreven. 100$ verdwenen. Bij gedistribueerde transacties kan een eenvoudige commit mislukken.

Stapsgewijze uitvoering van gedistribueerde transacties

Voor een vastlegging in twee fasen fungeert een van de databases als de coördinator van gedistribueerde transacties.

Stage 1

Een database begint transacties toe te passen en zich vervolgens voor te bereiden. Het verzendt voorbereide transacties naar andere databases in de vorm van voorbereide berichten. De tweede database ontvangt het bericht Voorbereiden en bereidt vervolgens de transactie voor. Prepare brengt veranderingen in de transactie met zich mee, maar verplicht zich niet. De vuile gegevens worden naar schijf geschreven voor persistentie. Zodra alle databases de transactie hebben voorbereid en alle informatie over de transactie op schijf is opgeslagen, is de voorbereidingsfase voltooid.

Stage 2

Vervolgens start de arbiter de commit-fase. Als de tweede database er om de een of andere reden niet in slaagt de transactie voor te bereiden, start de arbiter de terugdraaifase. Afhankelijk van of de voorbereiding succesvol is, wordt de transactie daarom vastgelegd of teruggedraaid. Een onderbreking in de laatste commit-fase kan worden hersteld, omdat de vereiste voorbereidingstransactie naar schijf is geschreven en opnieuw kan worden toegepast.

Commit in twee fasen is niet gerelateerd aan databases met één instantie, maar is relevant wanneer gegevens worden gerepliceerd over meerdere database-instanties.

Het is erg belangrijk om commit in twee fasen te ondersteunen bij logische replicatie.

Functioneel overzicht

Vóór de PG14-versie werden logische replicatietransacties pas gedecodeerd en gerepliceerd nadat de transactie was vastgelegd. Dit is om te voorkomen dat de replicatietransactie uiteindelijk wordt afgebroken.

Decodeer transactie bij commit

De logische replicatie van PG14 ondersteunt de opdrachten PREPARE TRANSACTION, COMMIT PREPARED en ROOLBACK PREPARED. Wanneer het PREPARE TRANSACTION-commando wordt gedecodeerd, wordt de transactie gedecodeerd en gekopieerd. TRANSACTION VOORBEREIDEN start het opnieuw afspelen en decoderen van transacties, net als COMMIT in WAL SENDER.

Transactie decoderen tijdens voorbereiding

We hebben ook een nieuwe plug-in-callback gedefinieerd om logische decoderingsplug-ins mogelijk te maken om verzending in twee fasen te ondersteunen.

Terugbellen

beschrijven

filter_voorbereiden_cb

Sta toe dat de plug-in transacties filtert die niet hoeven te worden gedecodeerd bij het voorbereiden volgens de GID die wordt gebruikt in de opdracht PREPARE TRANSACTION

beginnen_voorbereidencb

Begin van transactie voorbereiden

voorbereiden (cb)

Wordt aangeroepen wanneer de opdracht PREPARE TRANSACTION is gedecodeerd

plegen_voorbereid_cb

Wordt aangeroepen wanneer de COMMIT PREPARED-opdracht is gedecodeerd

terugdraaien_voorbereid_cb

Wordt aangeroepen wanneer de opdracht ROLLBACK PREPARED is gedecodeerd

Plug-in wijziging

test (decodering)

De plug-in is een uitvoerplug-in voor logische decodering, bijvoorbeeld om gebruikers te helpen hun eigen plug-in voor logische decodering te ontwikkelen. test_decoding ontvangt WAL via een logisch decoderingsmechanisme en decodeert deze in een tekstuele weergave van de uitgevoerde bewerking.

Het is aangepast om de nieuwe callback-functie in twee fasen te kunnen gebruiken en transacties te decoderen tijdens de voorbereiding

API's modificatie

pg_maak_logische_replicatiesleuf()

De API voegt een nieuwe optie toe om te specificeren of het slot twee-fasen commit ondersteunt. De uitvoerplug-in kan een replicatieslot gebruiken met een tweefasige optie om vastlegging in twee fasen te ondersteunen.

pg_maak_logische_replicatie_slot(slot_naam naam, plugin naam [, tijdelijke boolean, twee-fasen boolean ] )

Casestudy

Laten we eens kijken hoe we de gedecodeerde uitvoer van de tweefasige commit-transactie kunnen detecteren:

1) Maak een replicatieslot

Gebruik test_decoding als de uitvoerplug-in en geef true door, zodat de sleuf verzending en decodering in twee fasen ondersteunt.

postgres=# SELECT * FROM pg_maak_logische_replicatie_sleuf('regressiesleuf', 'test_decodering', false, true);

slot (naam | lsn)

ik

regressie (slot | 0/16B1970)

(1 rij)

2) Maak een tabel

postgres=# CREATE TABLE data(id seriële primaire sleutel, datatekst);

MAAK EEN TABEL

3) Detecteer de gedecodeerde uitvoerinhoud van transactie voorbereiden en transactie vastleggen;

postgres=# BEGIN

postgres=*# INVOEGEN IN gegevens(gegevens) WAARDEN('5');

postgres=*# TRANSACTIE VOORBEREIDEN 'test_prepared1';

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

lsn | xid | data

ik

0/1689DC0 ~ 529 ~ BEGIN 529

0/1689DC0 | 529 | tabel openbare.gegevens: INSERT: id[geheel getal]:3 gegevens[tekst]:'5'

0/1689FC0 | 529 | TRANSACTIE VOORBEREIDEN 'test_prepared1', txid 529

(3 rijen)

postgres=# COMMIT VOORBEREID 'test_prepared1';

postgres=# selecteer * uit pg_logisch_slot_getchanges('regressionslot', NULL, NULL);

lsn | xid | data

ik

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

(4 rijen)

postgres=# selecteer * uit gegevens;

id | gegevens

ik

1 | 5

(1 rij)

toekomst

De wijziging van PG14 in deze functie heeft een infrastructuur aan de decoderzijde die het in twee fasen verzenden van decodering tijdens de voorbereiding mogelijk maakt. We hebben ook de plug-in test_decoding aangepast om van deze infrastructuur te profiteren.

De volgende stap is het implementeren van de ondersteuning in twee fasen voor de grootste logische decoderingsplug-in in PG, de pgoutput-plug-in. Deze plug-in ondersteunt de PUBLISHER/SUBSCRIBER-modus van logische replicatie. Het is de meest gebruikte plug-in voor logische replicatie. Het Fujitsu OSS-team werkt samen met de open source-gemeenschap om deze functie aan PG15 toe te voegen.

Voor de tweefasige transactie in de gedistribueerde database moet PG ook ondersteuning bieden: de standby-machine informeert de host dat PREPARE is mislukt en start een rollback. Dit feedbackmechanisme wordt niet ondersteund in PG en is een van de richtingen voor toekomstige verbetering.

  Links:

6mbi25l-120

rm500uz-2 uur