La replicació no és una còpia de seguretat. O no? A continuació s'explica com hem utilitzat la rèplica diferida per recuperar-nos de la supressió accidental de dreceres.
La replicació no és un mitjà per fer una còpia de seguretat de bases de dades (gitlab-ce
Amb una rèplica ajornada, vam recuperar les dades en només 1,5 hores. Mira com va passar.
Recuperació puntual amb PostgreSQL
PostgreSQL té una funció integrada que restaura l'estat d'una base de dades a un moment concret. Es diu
Per utilitzar aquesta funció per a una còpia de seguretat en fred, regularment fem una còpia de seguretat bàsica de la base de dades i la desem en un arxiu (els arxius de GitLab viuen a
Què és la replicació diferida?
La replicació mandrosa és l'aplicació de canvis de WAL amb un retard. És a dir, la transacció es va produir en una hora X
, però apareixerà a la rèplica amb un retard d
en una hora X + d
.
PostgreSQL té 2 maneres de configurar una rèplica de base de dades física: recuperació de còpies de seguretat i replicació en temps real.
Com configurar la recuperació retardada d'un arxiu
recovery.conf
... Exemple:
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'
Amb aquests paràmetres, vam configurar una rèplica diferida amb recuperació de còpia de seguretat. Aquí s'utilitza restore_command
) de l'arxiu, i els canvis s'aplicaran al cap de vuit hores (recovery_min_apply_delay
). La rèplica vigilarà els canvis de la línia de temps a l'arxiu, per exemple a causa d'una migració per error del clúster (recovery_target_timeline
).
С recovery_min_apply_delay
Podeu configurar la rèplica en streaming amb un retard, però aquí hi ha un parell d'errors relacionats amb les ranures de rèplica, els comentaris en espera activa, etc. L'arxiu WAL permet evitar-los.
Paràmetre recovery_min_apply_delay
només apareixia a PostgreSQL 9.3. En versions anteriors, per a la rèplica diferida cal configurar la combinació pg_xlog_replay_pause(), pg_xlog_replay_resume()
) o mantenir els segments WAL a l'arxiu durant la durada del retard.
Com ho fa PostgreSQL?
És interessant veure com PostgreSQL implementa la recuperació mandrosa. Mirem-ho 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;
}
La conclusió és que el retard es basa en el temps físic registrat a la marca de temps de la transacció (xtime
). Com podeu veure, el retard només s'aplica a les confirmacions i no afecta altres entrades: tots els canvis s'apliquen directament i la confirmació es retarda, de manera que només veurem els canvis després del retard configurat.
Com utilitzar una rèplica retardada per restaurar dades
Suposem que tenim un clúster de bases de dades i una rèplica amb un retard de vuit hores en la producció. Vegem com recuperar dades amb un exemple
Quan vam conèixer el problema, nosaltres
SELECT pg_xlog_replay_pause();
Amb una pausa, no teníem cap risc que la rèplica repeteixi la sol·licitud DELETE
. Una cosa útil si necessiteu temps per esbrinar-ho tot.
La qüestió és que la rèplica diferida ha d'arribar al moment anterior a la sol·licitud DELETE
. Sabíem aproximadament l'hora física de l'eliminació. Hem esborrat recovery_min_apply_delay
i afegit recovery_target_time
в recovery.conf
. Així és com la rèplica arriba al moment adequat sense demora:
recovery_target_time = '2018-10-12 09:25:00+00'
Amb segells de temps, és millor reduir l'excés per no perdre's. És cert que com més gran sigui la disminució, més dades perdem. De nou, si ens perdem la petició DELETE
, tot s'esborrarà de nou i hauràs de començar de nou (o fins i tot fer una còpia de seguretat en fred per a PITR).
Vam reiniciar la instància de Postgres diferit i els segments WAL es van repetir fins a l'hora especificada. Podeu fer un seguiment del progrés en aquesta etapa preguntant:
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;
Si la marca de temps ja no canvia, la recuperació s'ha completat. L'acció es pot personalitzar recovery_target_action
La base de dades va tornar al seu estat abans d'aquella desafortunada sol·licitud. Ara podeu, per exemple, exportar dades. Vam exportar les dades de l'etiqueta suprimides i tots els enllaços a problemes i sol·licituds de combinació i les vam traslladar a la base de dades de producció. Si les pèrdues són a gran escala, simplement podeu promocionar la rèplica i utilitzar-la com a principal. Però aleshores es perdran tots els canvis després del punt al qual ens hem recuperat.
En lloc de segells de temps, és millor utilitzar identificadors de transacció. És útil registrar aquests identificadors, per exemple, per a sentències DDL (com ara DROP TABLE
), mitjançant l'ús de log_statements = 'ddl'
. Si tinguéssim un identificador de transacció, ho prendríem recovery_target_xid
i va executar-ho tot fins a la transacció abans de la sol·licitud DELETE
.
Tornar a la feina és molt senzill: elimina tots els canvis de recovery.conf
i reinicieu Postgres. La rèplica aviat tornarà a tenir un retard de vuit hores i estem preparats per a problemes futurs.
Beneficis de recuperació
Amb una rèplica diferida en lloc d'una còpia de seguretat en fred, no haureu de passar hores restaurant tota la imatge des de l'arxiu. Per exemple, triguem cinc hores a obtenir tota la còpia de seguretat bàsica de 2 TB. I després encara cal aplicar tot el WAL diari per recuperar l'estat desitjat (en el pitjor dels casos).
Una rèplica diferida és millor que una còpia de seguretat en fred de dues maneres:
- No cal eliminar tota la còpia de seguretat bàsica de l'arxiu.
- Hi ha una finestra fixa de vuit hores de segments WAL que s'ha de repetir.
També comprovem constantment si és possible fer un PITR des de WAL, i ràpidament detectaríem corrupció o altres problemes amb l'arxiu WAL controlant el retard de la rèplica ajornada.
En aquest exemple, vam trigar 50 minuts a restaurar-nos, és a dir, la velocitat era de 110 GB de dades WAL per hora (l'arxiu encara estava activat
Resultats: on una rèplica diferida és útil (i on no ho és)
Utilitzeu la replicació retardada com a primers auxilis si heu perdut dades accidentalment i heu detectat aquest problema amb el retard configurat.
Però tingueu en compte: la rèplica no és una còpia de seguretat.
La còpia de seguretat i la replicació tenen finalitats diferents. Una còpia de seguretat en fred serà útil si ho feu per accident DELETE
o DROP TABLE
. Fem una còpia de seguretat des de l'emmagatzematge en fred i restaurem l'estat anterior de la taula o de tota la base de dades. Però al mateix temps la petició DROP TABLE
es reprodueix gairebé a l'instant en totes les rèpliques del clúster de treball, de manera que la rèplica ordinària no ajudarà aquí. La pròpia replicació manté la base de dades disponible quan es lloguen servidors individuals i distribueix la càrrega.
Fins i tot amb una rèplica ajornada, de vegades necessitem una còpia de seguretat en fred en un lloc segur si es produeix una fallada del centre de dades, danys ocults o altres esdeveniments que no es noten immediatament. La replicació sola no serveix aquí.
Nota. Encès
Font: www.habr.com