A replicación non é unha copia de seguridade. Ou non? Así é como usamos a replicación diferida para recuperar atallos de eliminación accidental.
A replicación non é un medio para facer copias de seguridade das bases de datos (gitlab-ce
Cunha réplica diferida, recuperamos os datos en só 1,5 horas. Mira como pasou.
Recuperación puntual con PostgreSQL
PostgreSQL ten unha función integrada que restaura o estado dunha base de datos nun momento específico. Chámase
Para usar esta función para a copia de seguridade en frío, realizamos regularmente unha copia de seguridade básica da base de datos e almacenámola nun arquivo (os arquivos de GitLab viven en
Que é a replicación diferida?
A replicación preguiceira é a aplicación de cambios de WAL cun atraso. É dicir, a transacción produciuse nunha hora X
, pero aparecerá na réplica cun atraso d
nunha hora X + d
.
PostgreSQL ten 2 formas de configurar unha réplica de base de datos física: recuperación de copias de seguridade e replicación por streaming.
Como configurar a recuperación atrasada dun arquivo
recovery.conf
. Un exemplo:
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'
Con estes parámetros, configuramos unha réplica diferida con recuperación de copia de seguridade. Aquí úsase restore_command
) do arquivo, e os cambios aplicaranse despois de oito horas (recovery_min_apply_delay
). A réplica observará cambios na cronoloxía no arquivo, por exemplo debido a unha conmutación por falla do clúster (recovery_target_timeline
).
С recovery_min_apply_delay
Podes configurar a replicación en tempo real cun atraso, pero aquí hai un par de trampas relacionadas coas ranuras de replicación, os comentarios de espera activa, etc. O arquivo WAL permíteche evitalos.
Parámetro recovery_min_apply_delay
apareceu só en PostgreSQL 9.3. Nas versións anteriores, para a replicación diferida cómpre configurar a combinación pg_xlog_replay_pause(), pg_xlog_replay_resume()
) ou manter os segmentos WAL no arquivo durante o tempo que dure o atraso.
Como fai isto PostgreSQL?
É interesante ver como PostgreSQL implementa a recuperación perezosa. Vexamos 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;
}
A conclusión é que o atraso baséase no tempo físico rexistrado na marca de tempo da transacción (xtime
). Como podes ver, o atraso só se aplica ás confirmacións e non afecta a outras entradas: todos os cambios aplícanse directamente e a confirmación atrasase, polo que só veremos os cambios despois do atraso configurado.
Como usar unha réplica diferida para restaurar datos
Digamos que temos un clúster de bases de datos e unha réplica cun atraso de oito horas na produción. Vexamos como recuperar datos usando un exemplo
Cando nos enteramos do problema, nós
SELECT pg_xlog_replay_pause();
Cunha pausa, non tiñamos risco de que a réplica repetise a solicitude DELETE
. Unha cousa útil se necesitas tempo para descubrir todo.
A cuestión é que a réplica diferida debe chegar ao momento anterior á solicitude DELETE
. Coñecíamos aproximadamente o momento físico da eliminación. Borramos recovery_min_apply_delay
e engadiu recovery_target_time
в recovery.conf
. Así é como a réplica chega ao momento axeitado sen demora:
recovery_target_time = '2018-10-12 09:25:00+00'
Con marcas de tempo, é mellor reducir o exceso para non perder. É certo que canto maior sexa a diminución, máis datos perderemos. De novo, se perdemos a solicitude DELETE
, todo será eliminado de novo e terás que comezar de novo (ou incluso facer unha copia de seguridade en frío para PITR).
Reiniciamos a instancia de Postgres diferida e os segmentos WAL repetíronse ata o momento especificado. Podes seguir o progreso nesta fase preguntando:
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;
Se a marca de tempo xa non cambia, a recuperación está completa. A acción pódese personalizar recovery_target_action
A base de datos volveu ao seu estado antes daquela desafortunada solicitude. Agora podes, por exemplo, exportar datos. Exportamos os datos de etiquetas eliminados e todas as ligazóns a problemas e solicitudes de combinación e movémolos á base de datos de produción. Se as perdas son a gran escala, pode simplemente promocionar a réplica e usala como a principal. Pero entón todos os cambios despois do punto ao que nos recuperamos perderanse.
En lugar de marcas de tempo, é mellor usar ID de transacción. É útil rexistrar estes ID, por exemplo, para instrucións DDL (como DROP TABLE
), mediante o uso log_statements = 'ddl'
. Se tivésemos un ID de transacción, tomariamos recovery_target_xid
e executou todo ata a transacción antes da solicitude DELETE
.
Volver ao traballo é moi sinxelo: elimina todos os cambios de recovery.conf
e reinicie Postgres. A réplica terá en breve un atraso de oito horas de novo e estamos preparados para futuros problemas.
Beneficios de recuperación
Cunha réplica diferida en lugar dunha copia de seguridade en frío, non tes que gastar horas restaurando a imaxe completa do arquivo. Por exemplo, tardamos cinco horas en obter a copia de seguranza básica completa de 2 TB. E entón aínda tes que aplicar todo o WAL diario para recuperar o estado desexado (no peor dos casos).
Unha réplica diferida é mellor que unha copia de seguridade en frío de dous xeitos:
- Non é necesario eliminar a copia de seguridade básica completa do arquivo.
- Hai unha ventá fixa de oito horas de segmentos WAL que debe repetirse.
Tamén comprobamos constantemente se é posible facer un PITR desde WAL, e rapidamente notaríamos corrupción ou outros problemas co arquivo WAL supervisando o atraso da réplica diferida.
Neste exemplo, tardamos 50 minutos en restaurar, o que significa que a velocidade era de 110 GB de datos WAL por hora (o arquivo aínda estaba activo
Resultados: onde unha réplica diferida é útil (e onde non o é)
Use a replicación atrasada como primeiros auxilios se perdeu datos accidentalmente e notou este problema dentro do atraso configurado.
Pero ten en conta: a replicación non é unha copia de seguridade.
A copia de seguridade e a replicación teñen diferentes propósitos. Unha copia de seguridade en frío será útil se o fixeches accidentalmente DELETE
ou DROP TABLE
. Facemos unha copia de seguridade desde o almacenamento en frío e restauramos o estado anterior da táboa ou de toda a base de datos. Pero ao mesmo tempo a petición DROP TABLE
reprodúcese case ao instante en todas as réplicas do clúster de traballo, polo que a réplica ordinaria non axudará aquí. A propia replicación mantén dispoñible a base de datos cando os servidores individuais están inactivos e distribúe a carga.
Mesmo cunha réplica diferida, ás veces realmente necesitamos unha copia de seguridade en frío nun lugar seguro se se produce un fallo do centro de datos, danos ocultos ou outros eventos que non se notan inmediatamente. A replicación só non serve de nada aquí.
Nota. Activado
Fonte: www.habr.com