PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Posso reverter uma transação já confirmada? (perda de dados)


Não, você não pode desfazer, reverter ou reverter um commit.

PARE O BANCO DE DADOS!


(Observação:se você excluiu o diretório de dados do sistema de arquivos, NÃO interrompa o banco de dados. O conselho a seguir se aplica a um commit acidental de um DELETE ou similar, não um rm -rf /data/directory cenário).

Se esses dados forem importantes, PARE SEU BANCO DE DADOS AGORA e não reinicie. Use pg_ctl stop -m immediate para que nenhum ponto de verificação seja executado no desligamento.

Você não pode reverter uma transação depois de confirmada. Você precisará restaurar os dados dos backups ou usar a recuperação pontual, que deve ter sido configurada antes o acidente aconteceu.

Se você não tiver nenhum arquivamento PITR/WAL configurado e não tiver backups, você está com problemas reais.

Mitigação urgente


Assim que seu banco de dados estiver parado, você deve fazer uma cópia no nível do sistema de arquivos de todo o diretório de dados - a pasta que contém base , pg_clog , etc. Copie tudo para um novo local. Não faça nada com a cópia no novo local, é sua única esperança de recuperar seus dados se você não tiver backups. Faça outra cópia em algum armazenamento removível, se puder, e desconecte esse armazenamento do computador. Lembre-se, você precisa de absolutamente todas as partes do diretório de dados, incluindo pg_xlog etc. Nenhuma parte é sem importância.

Exatamente como fazer a cópia depende de qual sistema operacional você está executando. A localização do diretório de dados depende de qual sistema operacional você está executando e de como você instalou o PostgreSQL.

Como alguns dados poderiam ter sobrevivido


Se você parar seu banco de dados com rapidez suficiente, poderá ter esperança de recuperar alguns dados das tabelas. Isso porque o PostgreSQL usa o controle de simultaneidade de várias versões (MVCC) para gerenciar o acesso simultâneo ao seu armazenamento. Às vezes, ele escreverá novas versões das linhas que você atualiza na tabela, deixando as antigas no lugar, mas marcadas como "excluídas". Depois de um tempo, o autovaccum aparece e marca as linhas como espaço livre, para que possam ser substituídas por um INSERT posterior ou UPDATE . Assim, as versões antigas do UPDATE d linhas ainda podem estar por aí, presentes, mas inacessíveis.

Além disso, Pg escreve em duas fases. Os primeiros dados são gravados no log de gravação antecipada (WAL). Apenas uma vez que foi gravado no WAL e no disco de acesso, ele é copiado para o "heap" (as tabelas principais), possivelmente substituindo os dados antigos que estavam lá. O conteúdo WAL é copiado para o heap principal pelo bgwriter e por checkpoints periódicos. Por padrão, os pontos de verificação acontecem a cada 5 minutos. Se você conseguir parar o banco de dados antes que um ponto de verificação tenha ocorrido e o interrompeu fazendo um hard-kill, puxando o plugue da máquina ou usando pg_ctl em immediate modo que você pode ter capturado os dados antes do checkpoint acontecer, então é mais provável que seus dados antigos ainda estejam no heap.

Agora que você fez uma cópia completa no nível do sistema de arquivos do diretório de dados, você pode iniciar o backup do banco de dados se realmente precisar; os dados ainda terão desaparecido, mas você fez o que pode para se dar alguma esperança de talvez recuperá-los. Dada a escolha, eu provavelmente manteria o banco de dados desligado apenas por segurança.

Recuperação


Agora você pode precisar contratar um especialista nas entranhas do PostgreSQL para ajudá-lo em uma tentativa de recuperação de dados. Esteja preparado para pagar um profissional por seu tempo, possivelmente um pouco de tempo.

Eu postei sobre isso na lista de discussão do Pg, e Виктор Егоров linkou para o post de depesz no pg_dirtyread, que parece exatamente o que você quer, embora não recupere TOAST ed dados por isso é de utilidade limitada. Experimente, se você tiver sorte, pode funcionar.

Veja:pg_dirtyread no GitHub.

Eu removi o que escrevi nesta seção, pois está obsoleto por essa ferramenta.

Veja também fundamentos de armazenamento de linha do PostgreSQL

Prevenção


Veja minha entrada no blog Prevenindo a corrupção do banco de dados PostgreSQL.

Em uma nota lateral semi-relacionada, se você estivesse usando o commit de duas fases, você poderia ROLLBACK PREPARED para uma transação que foi preparada para confirmação, mas não totalmente confirmada. Isso é o mais próximo que você chega de reverter uma transação já confirmada e não se aplica à sua situação.