Replicarea nu este o copie de rezervă. Sau nu? Iată cum am folosit replicarea leneșă pentru recuperare prin ștergerea accidentală a comenzilor rapide.
Replicarea nu este instrumentul de backup al bazei de date (gitlab-ce
Cu replica întârziată, am recuperat datele în doar 1,5 ore. Vezi cum a fost.
Recuperare la un moment dat cu PostgreSQL
PostgreSQL are o funcție încorporată care restabilește starea unei baze de date la un anumit moment în timp. Se numeste
Pentru a folosi această caracteristică pentru o copie de rezervă la rece, facem în mod regulat o copie de rezervă a bazei de date de bază și o stocăm într-o arhivă (arhivele GitLab trăiesc în
Ce este replicarea întârziată?
Replicarea întârziată este aplicarea modificărilor de la WAL cu întârziere. Adică tranzacția a avut loc la ora X
, dar va apărea în replică cu întârziere d
într-o oră X + d
.
Există 2 moduri de a configura o replică fizică a bazei de date în PostgreSQL: restaurarea arhivei și replicarea în flux.
Cum să configurați recuperarea de rezervă întârziată
recovery.conf
... Exemplu:
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'
Cu aceste setări, am configurat o replică întârziată cu restaurarea arhivei. Folosit aici restore_command
) din arhivă, iar modificările vor fi aplicate după opt ore (recovery_min_apply_delay
). Replica va urmări modificările cronologiei din arhivă, cum ar fi din cauza unei failovere a clusterului (recovery_target_timeline
).
С recovery_min_apply_delay
puteți configura replicarea în flux cu latență, dar există câteva capcane asociate cu sloturile de replicare, feedback-ul de rezervă și așa mai departe. Arhiva WAL le evită.
Parametru recovery_min_apply_delay
a apărut doar în PostgreSQL 9.3. În versiunile anterioare, replicarea întârziată necesită o combinație de pg_xlog_replay_pause(), pg_xlog_replay_resume()
) sau păstrați segmentele WAL în arhivă pe durata întârzierii.
Cum face PostgreSQL?
Este interesant de văzut cum PostgreSQL implementează restaurarea leneșă. Să ne uităm la 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;
}
Concluzia este că întârzierea se bazează pe timpul fizic înregistrat în marcajul de timp al comenzii tranzacției (xtime
). După cum puteți vedea, întârzierea se aplică numai comitărilor și nu afectează alte înregistrări - toate modificările sunt aplicate direct, iar commit-ul este întârziat, așa că vom vedea modificările numai după întârzierea configurată.
Cum să utilizați replica leneșă pentru recuperarea datelor
Să presupunem că avem un cluster de baze de date în producție și o replică cu o întârziere de opt ore. Să vedem cum să recuperăm datele folosind un exemplu
Când am devenit conștienți de problemă, noi
SELECT pg_xlog_replay_pause();
Cu o pauză, nu am riscat ca replica să repete cererea DELETE
. Lucru util dacă aveți nevoie de timp pentru a înțelege totul.
Concluzia este că replica întârziată trebuie să ajungă în momentul dinaintea solicitării DELETE
. Știam aproximativ momentul fizic al îndepărtării. Am scos recovery_min_apply_delay
si adaugat recovery_target_time
в recovery.conf
. Deci replica ajunge la momentul potrivit fără întârziere:
recovery_target_time = '2018-10-12 09:25:00+00'
Cu marcajele de timp, este mai bine să reduceți excesul pentru a nu rata. Adevărat, cu cât scăderea este mai mare, cu atât pierdem mai multe date. Din nou, dacă sărim peste cerere DELETE
, totul va fi șters din nou și va trebui să o luați de la capăt (sau chiar să faceți o copie de rezervă rece pentru PITR).
Am repornit instanța Postgres întârziată și segmentele WAL au fost repetate până la ora specificată. Puteți urmări progresul în această etapă interogând:
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;
Dacă marca temporală nu se mai modifică, restaurarea este completă. Puteți personaliza acțiunea recovery_target_action
Baza de date a ajuns în statul înainte de acea cerere nefastă. Acum puteți, de exemplu, să exportați date. Am exportat datele etichetelor de la distanță și toate linkurile către probleme și solicitări de îmbinare și le-am transferat în baza de date de producție. Dacă pierderile sunt mari, poți pur și simplu să promovezi replica și să o folosești ca principală. Dar apoi toate schimbările se vor pierde după momentul în care ne-am revenit.
Este mai bine să utilizați ID-uri de tranzacție în loc de marcaje de timp. Este util să înregistrați aceste ID-uri, de exemplu, pentru instrucțiunile DDL (cum ar fi DROP TABLE
), prin utilizarea log_statements = 'ddl'
. Dacă am avea un ID de tranzacție, am lua recovery_target_xid
și a rulat totul până la tranzacție înainte de solicitare DELETE
.
Revenirea la muncă este foarte simplă: eliminați toate modificările din recovery.conf
și reporniți postgres. În curând, tacul va avea din nou o întârziere de opt ore și suntem pregătiți pentru probleme viitoare.
Beneficii de recuperare
Cu o replică întârziată, în loc de o copie de rezervă rece, nu trebuie să petreceți ore întregi restaurând întregul instantaneu din arhivă. De exemplu, avem nevoie de cinci ore pentru a obține întreaga copie de rezervă de bază de 2 TB. Și apoi mai trebuie să aplicați întregul WAL zilnic pentru a reveni la starea dorită (în cel mai rău caz).
O replică întârziată este mai bună decât o copie de rezervă rece în două moduri:
- Nu trebuie să obțineți întreaga copie de rezervă de bază din arhivă.
- Există o fereastră fixă de opt ore de segmente WAL care trebuie repetată.
De asemenea, verificăm în mod constant dacă WAL poate fi PITR și am observa rapid corupție sau alte probleme cu arhiva WAL prin monitorizarea întârzierii replicii întârziate.
În acest exemplu, ne-a luat 50 de minute pentru a restabili, adică viteza a fost de 110 GB de date WAL pe oră (arhiva era încă activată
Rezumat: unde este utilă o replică întârziată (și unde nu)
Utilizați replicarea întârziată ca prim ajutor dacă pierdeți din greșeală date și observați acest dezastru în termenul de întârziere configurat.
Dar rețineți: replicarea nu este o copie de rezervă.
Backup-ul și replicarea au scopuri diferite. O copie de rezervă rece va fi utilă dacă ați făcut-o accidental DELETE
sau DROP TABLE
. Facem o copie de rezervă din stocarea la rece și restaurăm starea anterioară a unui tabel sau a unei întregi baze de date. Dar în același timp și cererea DROP TABLE
reprodus aproape instantaneu în toate replicile de pe clusterul de lucru, astfel încât replicarea regulată nu se va salva aici. Replicarea în sine menține baza de date disponibilă atunci când serverele individuale sunt închiriate și distribuie încărcarea.
Chiar și cu o copie întârziată, uneori avem nevoie de o copie de rezervă la rece într-un loc sigur, dacă dintr-o dată apare o defecțiune a centrului de date, daune ascunse sau alte evenimente pe care nu le observi imediat. Aici dintr-o replicare nu are sens.
Nota. pe
Sursa: www.habr.com