Replicatie is geen back-up. Of niet? Hier ziet u hoe we uitgestelde replicatie hebben gebruikt om te herstellen van het per ongeluk verwijderen van snelkoppelingen.
Replicatie is geen manier om een back-up van databases te maken (gitlab-ce
Met een uitgestelde replica hebben we de gegevens in slechts 1,5 uur hersteld. Kijk hoe het gebeurde.
Point-in-time herstel met PostgreSQL
PostgreSQL heeft een ingebouwde functie die de status van een database herstelt naar een specifiek tijdstip. Het heet
Om deze functie voor koude back-up te gebruiken, maken we regelmatig een basisback-up van de database en slaan deze op in een archief (GitLab-archieven leven in
Wat is uitgestelde replicatie?
Luie replicatie is het met vertraging toepassen van wijzigingen uit WAL. Dat wil zeggen dat de transactie binnen een uur plaatsvond X
, maar het verschijnt met vertraging in de replica d
over een uur X + d
.
PostgreSQL heeft twee manieren om een fysieke databasereplica in te stellen: back-upherstel en streaming-replicatie.
Uitgesteld herstel vanuit een archief instellen
recovery.conf
. Voorbeeld:
standby_mode = 'on'
restore_command = '/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-fetch -p 4 "%f" "%p"'
recovery_min_apply_delay = '8h'
recovery_target_timeline = 'latest'
Met deze parameters hebben we een uitgestelde replica met back-upherstel geconfigureerd. Hier wordt het gebruikt restore_command
) uit het archief en wijzigingen worden na acht uur toegepast (recovery_min_apply_delay
). De replica let op tijdlijnwijzigingen in het archief, bijvoorbeeld als gevolg van een clusterfailover (recovery_target_timeline
).
С recovery_min_apply_delay
U kunt streamingreplicatie met vertraging instellen, maar er zijn hier een aantal valkuilen die te maken hebben met replicatieslots, hot standby-feedback, enzovoort. Met het WAL-archief kunt u ze vermijden.
Parameter recovery_min_apply_delay
verscheen alleen in PostgreSQL 9.3. In eerdere versies moest u voor uitgestelde replicatie de combinatie configureren pg_xlog_replay_pause(), pg_xlog_replay_resume()
) of bewaar WAL-segmenten in het archief gedurende de duur van de vertraging.
Hoe doet PostgreSQL dit?
Het is interessant om te zien hoe PostgreSQL lui herstel implementeert. Laten we eens kijken recoveryApplyDelay(XlogReaderState)
static bool
recoveryApplyDelay(XLogReaderState *record)
{
uint8 xact_info;
TimestampTz xtime;
long secs;
int microsecs;
/* nothing to do if no delay configured */
if (recovery_min_apply_delay <= 0)
return false;
/* no delay is applied on a database not yet consistent */
if (!reachedConsistency)
return false;
/*
* Is it a COMMIT record?
*
* We deliberately choose not to delay aborts since they have no effect on
* MVCC. We already allow replay of records that don't have a timestamp,
* so there is already opportunity for issues caused by early conflicts on
* standbys.
*/
if (XLogRecGetRmid(record) != RM_XACT_ID)
return false;
xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
if (xact_info != XLOG_XACT_COMMIT &&
xact_info != XLOG_XACT_COMMIT_PREPARED)
return false;
if (!getRecordTimestamp(record, &xtime))
return false;
recoveryDelayUntilTime =
TimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay);
/*
* Exit without arming the latch if it's already past time to apply this
* record
*/
TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,
&secs, µsecs);
if (secs <= 0 && microsecs <= 0)
return false;
while (true)
{
// Shortened:
// Use WaitLatch until we reached recoveryDelayUntilTime
// and then
break;
}
return true;
}
Het komt erop neer dat de vertraging gebaseerd is op de fysieke tijd die is vastgelegd in het tijdstempel van de transactievastlegging (xtime
). Zoals je kunt zien, is de vertraging alleen van toepassing op commits en heeft deze geen invloed op andere items. Alle wijzigingen worden direct toegepast en de commit wordt uitgesteld, dus we zullen de wijzigingen pas zien na de geconfigureerde vertraging.
Hoe u een vertraagde replica gebruikt om gegevens te herstellen
Laten we zeggen dat we een databasecluster en een replica hebben met een productievertraging van acht uur. Laten we eens kijken hoe u gegevens kunt herstellen aan de hand van een voorbeeld
Toen we over het probleem hoorden, hebben we
SELECT pg_xlog_replay_pause();
Met een pauze hadden we geen risico dat de replica het verzoek zou herhalen DELETE
. Handig als je tijd nodig hebt om alles uit te zoeken.
Het punt is dat de uitgestelde replica het moment vóór het verzoek moet bereiken DELETE
. We kenden ongeveer het fysieke tijdstip van verwijdering. Wij hebben verwijderd recovery_min_apply_delay
en voegde toe recovery_target_time
в recovery.conf
. Zo bereikt de replica zonder vertraging het juiste moment:
recovery_target_time = '2018-10-12 09:25:00+00'
Met tijdstempels is het beter om het eigen risico te verminderen, zodat u het niet mist. Het is waar dat hoe groter de daling is, hoe meer gegevens we verliezen. Nogmaals, als we het verzoek missen DELETE
, wordt alles weer verwijderd en moet je opnieuw beginnen (of zelfs een koude back-up maken voor PITR).
We hebben de uitgestelde Postgres-instantie opnieuw opgestart en de WAL-segmenten werden herhaald tot de opgegeven tijd. U kunt de voortgang in deze fase volgen door het volgende te vragen:
SELECT
-- current location in WAL
pg_last_xlog_replay_location(),
-- current transaction timestamp (state of the replica)
pg_last_xact_replay_timestamp(),
-- current physical time
now(),
-- the amount of time still to be applied until recovery_target_time has been reached
'2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;
Als de tijdstempel niet meer verandert, is het herstel voltooid. Actie kan worden aangepast recovery_target_action
De database keerde terug naar de staat van vóór dat ongelukkige verzoek. Nu kunt u bijvoorbeeld gegevens exporteren. We hebben de verwijderde etiketgegevens en alle links naar uitgaven en samenvoegverzoeken geëxporteerd en naar de productiedatabase verplaatst. Als de verliezen grootschalig zijn, kunt u eenvoudig de replica promoten en als belangrijkste gebruiken. Maar dan zullen alle veranderingen na het punt waarop we zijn hersteld verloren gaan.
In plaats van tijdstempels is het beter om transactie-ID's te gebruiken. Het is handig om deze ID’s vast te leggen, bijvoorbeeld voor DDL-statements (zoals DROP TABLE
), door het gebruiken van log_statements = 'ddl'
. Als we een transactie-ID hadden, zouden we dat nemen recovery_target_xid
en voerde alles uit tot aan de transactie vóór het verzoek DELETE
.
Weer aan de slag gaan is heel eenvoudig: verwijder alle wijzigingen uit recovery.conf
en herstart Postgres. De replica heeft binnenkort weer een vertraging van acht uur en we zijn voorbereid op toekomstige problemen.
Herstelvoordelen
Met een uitgestelde replica in plaats van een koude back-up hoeft u geen uren te besteden aan het herstellen van de volledige image uit het archief. Het kost ons bijvoorbeeld vijf uur om de volledige standaardback-up van 2 TB te krijgen. En dan moet je nog de hele dagelijkse WAL toepassen om (in het ergste geval) weer in de gewenste staat te komen.
Een uitgestelde replica is op twee manieren beter dan een koude back-up:
- Het is niet nodig om de volledige basisback-up uit het archief te verwijderen.
- Er is een vast venster van acht uur met WAL-segmenten dat moet worden herhaald.
We controleren ook voortdurend of het mogelijk is om van WAL een PITR te maken, en we zouden snel corruptie of andere problemen met het WAL-archief opmerken door de vertraging van de uitgestelde replica te monitoren.
In dit voorbeeld kostte het ons 50 minuten om te herstellen, wat betekent dat de snelheid 110 GB aan WAL-gegevens per uur bedroeg (het archief stond nog steeds aan
Resultaten: waar een uitgestelde replica nuttig is (en waar niet)
Gebruik vertraagde replicatie als eerste hulp als u per ongeluk gegevens bent kwijtgeraakt en dit probleem binnen de geconfigureerde vertraging hebt opgemerkt.
Maar onthoud: replicatie is geen back-up.
Back-up en replicatie hebben verschillende doeleinden. Een koude back-up is handig als u deze per ongeluk hebt gemaakt DELETE
of DROP TABLE
. Wij maken een back-up van de koude opslag en herstellen de vorige staat van de tabel of de gehele database. Maar tegelijkertijd het verzoek DROP TABLE
wordt vrijwel onmiddellijk gereproduceerd in alle replica's op het werkcluster, dus gewone replicatie zal hier niet helpen. Replicatie zelf houdt de database beschikbaar wanneer individuele servers worden verhuurd en verdeelt de belasting.
Zelfs met een uitgestelde replica hebben we soms echt een koude back-up op een veilige plek nodig als er zich een datacenterstoring, verborgen schade of andere gebeurtenissen voordoen die niet direct merkbaar zijn. Replicatie alleen heeft hier geen zin.
Noot. op
Bron: www.habr.com