Replikacija ni varnostna kopija. ali ne? Tukaj je opisano, kako smo uporabili odloženo podvajanje za obnovitev po nenamernem brisanju bližnjic.
Replikacija ni sredstvo za varnostno kopiranje baz podatkov (gitlab-ce
Z odloženo repliko smo obnovili podatke v samo 1,5 ure. Poglej, kako se je zgodilo.
Obnovitev v času s PostgreSQL
PostgreSQL ima vgrajeno funkcijo, ki obnovi stanje baze podatkov na določeno časovno točko. Se imenuje
Za uporabo te funkcije za hladno varnostno kopiranje redno izdelujemo osnovno varnostno kopijo baze podatkov in jo shranimo v arhiv (arhivi GitLab živijo v
Kaj je odložena replikacija?
Leno podvajanje je uporaba sprememb iz WAL z zamikom. To pomeni, da se je transakcija zgodila v eni uri X
, vendar se bo v replici pojavil z zamikom d
v eni uri X + d
.
PostgreSQL ima dva načina za nastavitev fizične replike baze podatkov: obnovitev varnostne kopije in pretočno replikacijo.
Kako nastaviti odloženo obnovitev iz arhiva
recovery.conf
... Primer:
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'
S temi parametri smo konfigurirali odloženo repliko z obnovitvijo varnostne kopije. Tukaj se uporablja restore_command
) iz arhiva, spremembe pa bodo uveljavljene po osmih urah (recovery_min_apply_delay
). Replika bo opazovala spremembe časovnice v arhivu, na primer zaradi preklopa gruče (recovery_target_timeline
).
С recovery_min_apply_delay
Pretočno replikacijo lahko nastavite z zamikom, vendar je tukaj nekaj pasti, ki so povezane z režami za replikacijo, povratnimi informacijami v vročem stanju pripravljenosti itd. Arhiv WAL vam omogoča, da se jim izognete.
Parameter recovery_min_apply_delay
pojavil šele v PostgreSQL 9.3. V prejšnjih različicah morate za odloženo podvajanje konfigurirati kombinacijo pg_xlog_replay_pause(), pg_xlog_replay_resume()
) ali obdržite segmente WAL v arhivu za čas zakasnitve.
Kako to počne PostgreSQL?
Zanimivo je videti, kako PostgreSQL izvaja leno obnovitev. Poglejmo si 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;
}
Bistvo je, da zakasnitev temelji na fizičnem času, zabeleženem v časovnem žigu izvršitve transakcije (xtime
). Kot lahko vidite, zakasnitev velja samo za objave in ne vpliva na druge vnose - vse spremembe se uporabijo neposredno, potrditev pa je zakasnjena, zato bomo spremembe videli šele po konfigurirani zakasnitvi.
Kako uporabiti odloženo repliko za obnovitev podatkov
Recimo, da imamo gručo baze podatkov in repliko z osemurno zamudo v proizvodnji. Poglejmo, kako obnoviti podatke na primeru
Ko smo izvedeli za težavo, smo
SELECT pg_xlog_replay_pause();
S premorom nismo imeli nobenega tveganja, da bi replika ponovila zahtevo DELETE
. Uporabna stvar, če potrebujete čas, da vse ugotovite.
Bistvo je, da mora odložena replika doseči trenutek pred zahtevo DELETE
. Fizični čas odstranitve smo približno poznali. Izbrisali smo recovery_min_apply_delay
in dodal recovery_target_time
в recovery.conf
. Tako replika pride v pravi trenutek brez zamude:
recovery_target_time = '2018-10-12 09:25:00+00'
Pri časovnih žigih je bolje zmanjšati presežek, da ne zamudite. Res je, večje kot je zmanjšanje, več podatkov izgubimo. Še enkrat, če zamudimo zahtevo DELETE
, bo vse znova izbrisano in morali boste začeti znova (ali celo narediti hladno varnostno kopijo za PITR).
Znova smo zagnali odloženi primerek Postgres in segmenti WAL so se ponavljali do določenega časa. Na tej stopnji lahko spremljate napredek tako, da vprašate:
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;
Če se časovni žig ne spremeni več, je obnovitev končana. Ukrep je mogoče prilagoditi recovery_target_action
Baza podatkov se je vrnila v stanje pred to nesrečno zahtevo. Zdaj lahko na primer izvozite podatke. Izvozili smo podatke o izbrisanih oznakah in vse povezave do težav in zahtev za združitev ter jih premaknili v produkcijsko bazo podatkov. Če so izgube velikega obsega, lahko preprosto promovirate repliko in jo uporabite kot glavno. Toda potem bodo vse spremembe po točki, do katere smo si opomogli, izgubljene.
Namesto časovnih žigov je bolje uporabiti ID-je transakcij. Te ID-je je koristno zabeležiti na primer za stavke DDL (kot npr DROP TABLE
), z uporabo log_statements = 'ddl'
. Če bi imeli ID transakcije, bi vzeli recovery_target_xid
in opravil vse do transakcije pred zahtevo DELETE
.
Vrnitev na delo je zelo preprosta: odstranite vse spremembe iz recovery.conf
in znova zaženite Postgres. Replika bo kmalu spet imela osemurno zamudo in pripravljeni smo na prihodnje težave.
Prednosti okrevanja
Z odloženo repliko namesto hladne varnostne kopije vam ni treba porabiti ur za obnavljanje celotne slike iz arhiva. Na primer, potrebujemo pet ur, da pridobimo celotno osnovno varnostno kopijo 2 TB. In potem morate še vedno uporabiti celoten dnevni WAL, da se vrnete v želeno stanje (v najslabšem primeru).
Odložena replika je boljša od hladne varnostne kopije na dva načina:
- Iz arhiva ni treba odstraniti celotne osnovne varnostne kopije.
- Obstaja fiksno osemurno okno segmentov WAL, ki jih je treba ponoviti.
Prav tako nenehno preverjamo, ali je mogoče narediti PITR iz WAL, in hitro bi opazili poškodbe ali druge težave z arhivom WAL, če bi spremljali zaostajanje odložene replike.
V tem primeru smo za obnovitev potrebovali 50 minut, kar pomeni, da je bila hitrost 110 GB podatkov WAL na uro (arhiv je bil še vedno vklopljen
Rezultati: kje je odložena replika uporabna (in kje ne)
Uporabite zakasnjeno podvajanje kot prvo pomoč, če ste pomotoma izgubili podatke in opazili to težavo znotraj konfigurirane zakasnitve.
Vendar ne pozabite: replikacija ni varnostna kopija.
Varnostno kopiranje in podvajanje imata različne namene. Hladna varnostna kopija vam bo prav prišla, če ste jo pomotoma naredili DELETE
ali DROP TABLE
. Naredimo varnostno kopijo iz hladilnice in povrnemo prejšnje stanje tabele ali celotne baze podatkov. A hkrati zahteva DROP TABLE
se skoraj takoj reproducira v vseh replikah v delujoči gruči, zato navadna replikacija tukaj ne bo pomagala. Replikacija sama ob oddaji posameznih strežnikov ohranja na voljo bazo podatkov in porazdeli obremenitev.
Tudi z odloženo repliko včasih resnično potrebujemo hladno varnostno kopijo na varnem mestu, če pride do okvare podatkovnega centra, skrite poškodbe ali drugih dogodkov, ki niso takoj opazni. Replikacija sama po sebi tukaj ni uporabna.
Obvestilo. Na
Vir: www.habr.com