A replicação não é um backup. Ou não? Veja como usamos a replicação preguiçosa para recuperação, excluindo atalhos acidentalmente.
A replicação não é sua ferramenta de backup de banco de dados (gitlab-ce
Com a réplica atrasada, recuperamos os dados em apenas 1,5 horas. Veja como foi.
Recuperação pontual com PostgreSQL
O PostgreSQL possui uma função interna que restaura o estado de um banco de dados para um ponto específico no tempo. é chamado
Para usar esse recurso para um backup frio, fazemos regularmente um backup de banco de dados básico e o armazenamos em um arquivo (os arquivos do GitLab residem em
O que é replicação atrasada?
A replicação atrasada é a aplicação de alterações do WAL com um atraso. Ou seja, a transação ocorreu na hora X
, mas aparecerá na réplica com um atraso d
em uma hora X + d
.
Existem 2 maneiras de configurar uma réplica de banco de dados física no PostgreSQL: restauração de arquivo e replicação de streaming.
Como configurar a recuperação de backup atrasada
recovery.conf
. 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'
Com essas configurações, configuramos uma réplica atrasada com restauração de arquivo. Usado aqui restore_command
) do arquivo, e as alterações serão aplicadas após oito horas (recovery_min_apply_delay
). A réplica observará as alterações na linha do tempo no arquivo, como devido a um failover de cluster (recovery_target_timeline
).
С recovery_min_apply_delay
você pode configurar a replicação de streaming de latência, mas há algumas armadilhas associadas a slots de replicação, feedback de hot spare e assim por diante. O arquivo WAL os evita.
Parâmetro recovery_min_apply_delay
apareceu apenas no PostgreSQL 9.3. Nas versões anteriores, a replicação atrasada requer uma combinação de pg_xlog_replay_pause(), pg_xlog_replay_resume()
) ou mantenha os segmentos WAL no arquivo durante o atraso.
Como o PostgreSQL faz isso?
É interessante ver como o PostgreSQL implementa a restauração preguiçosa. Vamos olhar para 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;
}
O ponto principal é que o atraso é baseado no tempo físico registrado no registro de data e hora da confirmação da transação (xtime
). Como você pode ver, o atraso se aplica apenas aos commits e não afeta outros registros - todas as alterações são aplicadas diretamente e o commit é atrasado, portanto veremos as alterações somente após o atraso configurado.
Como usar a réplica preguiçosa para recuperação de dados
Digamos que temos um cluster de banco de dados em produção e uma réplica com atraso de oito horas. Vamos ver como recuperar dados usando um exemplo
Quando percebemos o problema,
SELECT pg_xlog_replay_pause();
Com uma pausa, não corríamos o risco de a réplica repetir a solicitação DELETE
. Coisa útil se você precisar de tempo para descobrir tudo.
O ponto principal é que a réplica atrasada deve atingir o momento antes da solicitação DELETE
. Sabíamos aproximadamente o tempo físico da remoção. Nós removemos recovery_min_apply_delay
e acrescentou recovery_target_time
в recovery.conf
. Assim, a réplica chega ao momento certo sem demora:
recovery_target_time = '2018-10-12 09:25:00+00'
Com timestamps, é melhor reduzir o excesso para não errar. É verdade que quanto maior a diminuição, mais dados perdemos. Novamente, se pularmos a solicitação DELETE
, tudo será apagado novamente e você terá que recomeçar (ou até mesmo fazer um backup frio para PITR).
Reiniciamos a instância atrasada do Postgres e os segmentos WAL foram repetidos até o tempo especificado. Você pode acompanhar o progresso neste estágio consultando:
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 o registro de data e hora não for mais alterado, a restauração estará concluída. Você pode personalizar a ação recovery_target_action
O banco de dados chegou ao estado anterior a essa solicitação malfadada. Agora você pode, por exemplo, exportar dados. Exportamos os dados do rótulo remoto e todos os links para problemas e solicitações de mesclagem e os transferimos para o banco de dados de produção. Se as perdas forem grandes, você pode simplesmente promover a réplica e usá-la como principal. Mas então todas as mudanças serão perdidas após o momento em que nos recuperamos.
É melhor usar IDs de transação em vez de timestamps. É útil registrar esses IDs, por exemplo, para instruções DDL (como DROP TABLE
), usando log_statements = 'ddl'
. Se tivéssemos um ID de transação, levaríamos recovery_target_xid
e executei tudo até a transação antes da solicitação DELETE
.
Voltar ao trabalho é muito simples: remova todas as alterações de recovery.conf
e reinicie o postgres. Em breve, a deixa terá novamente um atraso de oito horas e estamos prontos para problemas futuros.
Benefícios de Recuperação
Com uma réplica atrasada, em vez de um backup frio, você não precisa gastar horas restaurando todo o instantâneo do arquivo. Por exemplo, precisamos de cinco horas para obter todo o backup básico de 2 TB. E então você ainda tem que aplicar todo o WAL diário para recuperar ao estado desejado (no pior caso).
Uma réplica atrasada é melhor do que um backup frio de duas maneiras:
- Você não precisa obter todo o backup básico do arquivo.
- Há uma janela fixa de oito horas de segmentos WAL que deve ser repetida.
Além disso, estamos constantemente verificando se WAL pode ser PITRed, e notamos rapidamente corrupção ou outros problemas com o arquivo WAL monitorando o backlog da réplica atrasada.
Neste exemplo, levamos 50 minutos para restaurar, ou seja, a velocidade era de 110 GB de dados WAL por hora (o arquivo ainda estava em
Resumo: onde uma réplica atrasada é útil (e onde não)
Use a replicação atrasada como um primeiro socorro se você acidentalmente perder dados e perceber esse desastre dentro do atraso configurado.
Mas lembre-se: a replicação não é um backup.
O backup e a replicação têm finalidades diferentes. Um backup frio será útil se você acidentalmente DELETE
ou DROP TABLE
. Fazemos um backup do armazenamento frio e restauramos o estado anterior de uma tabela ou de um banco de dados inteiro. Mas ao mesmo tempo o pedido DROP TABLE
reproduzido quase instantaneamente em todas as réplicas no cluster de trabalho, portanto, a replicação regular não será salva aqui. A própria replicação mantém o banco de dados disponível quando os servidores individuais são alugados e distribui a carga.
Mesmo com uma réplica atrasada, às vezes realmente precisamos de um backup frio em um local seguro, se de repente houver uma falha no data center, danos ocultos ou outros eventos que você não percebe imediatamente. Aqui de uma replicação não há sentido.
Nota. Em
Fonte: habr.com