/ Banco de dados

Subindo um cluster no Postgres em poucos minutos

A facilidade de criar um cluster no Postgres ja me salvou de algumas dores de cabeça. Fiquei tão impressionado que resolvi escrever este post. Se você é um DBA ou alguém precisando de socorro, esta estratégia pode ser empregada em inúmeros cenários.
No teste que irei descrever abaixo, o cluster montado foi utilizado para realizar restore da base do cliente e fornecer os dados perdidos. Vamos ao que interessa!

O ambiente

Alguns detalhes técnicos que precisamos conhecer:

  • VM com S.O. Linux
  • Postgres 10.8
  • Log archive ativo
  • Backup full do servidor realizado pelo pg_basebackup

Problema hipotético

Digamos que, acidentalmente um grupo de registros foi indevidamente eliminado ou alterado no ambiente do cliente. E nós, precisamos de alguma forma recuperá-los com o menor esforço possivel. Quando digo "menor esforço possivel" entenda que não quero considerar um restore da base do cliente a primeira opção na lista de possiveis ações para resolver o problema.
pensando

Analise prévia

  1. Precisamos avaliar o estrago e ver a quantidade de registros ou tabelas afetadas pelo acidente.
  2. Avaliar se realmente é necessário reverter a operação fazendo o uso de restore e correr o risco de perder outras coisas.
  3. Estimar o esforço para realizar o tal restore na base de produção do cliente.
    o-que-eu-fa-o

As questões anteriores são importantes e devem ser discutidas com cuidado. Se o estrago foi grande, o restore da base do cliente passa a ficar interessante.
Mas, se o grupo de registros a ser recuperado não vale tamanho esforço. Ótimo, então vamos falar da estratégia que me motivou a escrever este post. E, certamente ela sairá mais barata para este cenário.

Go horse...

Primeiro, precisamos avaliar se o servidor atual do cliente tem espaço suficiente para realizar um restore full.

Opaaaa... pera aí... eu tinha dito antes que não queria considerar o restore como a primeira ação da lista. Não foi?

Verdade, mas estava falando de restore direto no ambiente de produção do cliente.
Muito bem, na abertura do post falei da facilidade em subir um cluster no Postgres. Pois então, esta é a dica de ouro. Vamos subir um cluster e fazer o restore nele e em seguida recuperar o que for preciso!
feliz

Passo 1:

Descompacte o backup full em uma área do servidor de sua preferência. Geralmente, o backup realizado pelo pg_basebackup é um arquivo TAR compactado.

$ tar -xzf base.tar.gz -C pgdata

Neste exemplo, o arquivo base.tar.gz esta sendo descompactado na pasta pgdata.

Passo 2:

Dentro da pasta pgdata, iremos criar o arquivo recovery.conf. Ele tem orientações importantes para o processo de restore que iniciará ao subir o cluster:

restore_command = 'cp /wal_archive/%f "%p"'
recovery_target_time = '2020-07-30 16:29'

1ª linha: comando para copiar os logs (archive) e trazer para dentro do cluster.
2ª linha: horario limite onde se deve parar de aplicar os logs. Neste caso, foi informado o horario para evitar que os logs com os dados perdidos fossem carregados.

Passo 3:

Agora iremos inicialiar o cluster fazendo o uso do pg_ctl.

Importante: Iremos configurar uma nova pasta de dados e uma nova porta, diferente do servidor que está ativo atualmente que é o ambiente de produção.

$ ./pg_ctl start -D /mnt/backup/pgdata -o "-p 6000"

Neste exemplo, o cluster usará a pasta de dados /mnt/backup/pgdata e a porta 6000.
Aguarde o cluster inicializar e aplicar os logs até o ponto desejado. Se tudo correr bem, você verá a mensagem dizendo que o servidor foi iniciado e esta pronto para receber conexões.

A partir deste momento, já podemos conectar no cluster e recuperar as informações perdidas ou alteradas e repassar ao ambiente oficial de produção.

Calma ai que vou explicar uma forma interessante de fazer os dois servidores se falarem.
feliz2-1

Passo 4:

Fazendo o uso do PgAdmin, conecte-se no servidor de destino, aquele que irá receber os dados. Crie um script com o conteudo abaixo. E claro, faça os devidos ajustes com as informações do ambiente.

-- Habilita recurso para criar tabela estrangeira
CREATE EXTENSION postgres_fdw;

-- Registra o servidor de origem dos dados (o cluster)
CREATE SERVER SRV_CLUSTER_SIGA
	FOREIGN DATA WRAPPER postgres_fdw
	OPTIONS (host '10.0.0.10', port '6000', dbname 'DB_SIGA');
		
-- Concede ao usuario postgres local permissao no servidor remoto
CREATE USER MAPPING FOR postgres 
	SERVER SRV_CLUSTER_SIGA
	OPTIONS (user 'postgres', password '....');
	
-- Cria esquema local para receber as tabelas estrangeiras
CREATE SCHEMA cluster_siga
    AUTHORIZATION postgres;

-- Cria a tabela estrangeira
CREATE FOREIGN TABLE cluster_siga.tabela_origem (
	id integer ,
	nome text
	)
	SERVER SRV_CLUSTER_SIGA
	OPTIONS (schema_name 'public', table_name 'tabela_origem');

Para evitar surpresas, execute cada comando separadamente. Depois de tudo isso é só usar a tabela estrangeira como se fosse uma tabela do banco local. Não esqueça que ela foi criada em um esquema diferente.
surpreso

Terminado o trabalho de recuperação dos dados, encerre o cluster com o comando abaixo. Não esqueça de elimar a pasta pgdata. Ela não terá mais uso com o cluster desligado.

$ ./pg_ctl stop -D /mnt/backup/pgdata -o "-p 6000"

Isso é tudo pessoal. Boa semana a todos.

Por isso, vistam toda a armadura de Deus, para que possam resistir no dia mau e permanecer inabaláveis, depois de terem feito tudo.
Efésios 6:13

Referências

https://www.percona.com/blog/2018/06/28/faster-point-in-time-recovery-pitr-postgresql-using-delayed-standby/
https://severalnines.com/database-blog/point-time-postgresql-database-restoration
https://www.postgresql.org/docs/10/app-pg-ctl.html
https://www.postgresql.org/docs/10/postgres-fdw.html