Hoje enfrentei um problema difícil no trabalho, um cliente pediu para recuperar um backup de um banco que acidentalmente teve seus dados apagados, como levei algum tempo para juntar as peças e montar o quebra cabeça resolvi postar aqui pra compartilhar com todos essa experiência.
Então, vamos ao cenário:
- Cliente pede para recuperar o backup de um banco no MySQL
- Percebi que não tinhamos backup em dump daquele banco, somente backup em tarball de todo o /var/lib/mysql (normalmente é lá que ficam os arquivos contendo os dados e índices dos bancos de dados)
A partir deste ponto normalmente se pensa que basta recuperar o diretório com o nome do banco de dentro do tarball, ou seja extrair do tarball /var/lib/mysql/nome_banco. Acontece que isso geralmente funciona, mas para bancos com tabelas MyISAM. Bancos com tabelas InnoDB possuem uma pequena diferença no MySQL, seus dados não ficam autocontidos no diretório de nome do banco, mas sim dentro do arquivo /var/lib/mysql/ibdata1, este arquivo vai conter os dados de todos os bancos que utilizarem a engine InnoDB, e é justamente por causa disso que NÃO podemos restaurar o backup de um banco específico sobrescrevendo o ibdata1, pois senão iremos voltar dados para o passado no banco de dados de TODOS os usuários!!!
O que então precisamos fazer?
Pré-requisitos:
- Ter uma máquina extra (física ou virtual)
- O MySQL instalado nesta máquina extra e sem estar sendo utilizado em produção
A primeira coisa que devemos fazer é copiar para a máquina extra o /var/lib/mysql/ibdata1 e o /var/lib/mysql/nome_do_banco que foram extraídos do nosso tarball com o backup. Antes de fazer alguma alteração nos dados do MySQL vamos parar o banco com o comando (em distribuição debian):
invoke-rc.d mysql stop
Depois de parar o MySQL vamos fazer uma cópia do /var/lib/mysql só por precaução:
cp -a /var/lib/mysql /var/lib/mysql.20090617
Agora vamos sobrescrever o /var/lib/mysql/ibdata1 com aquele que extraímos do tarball e em seguida copiar o diretório contendo os demais arquivos do banco, aquele /var/lib/mysql/nome_do_banco.
Para garantir vamos ajustar as permissões:
chown -R mysql:mysql /var/lib/mysql/ibdata1 /var/lib/mysql/nome_do_banco
Neste ponto já podemos levantar o MySQL novamente:
invoke-rc.d mysql start
Nos logs do MySQL você vai perceber que ele vai acusar diversos erros, pois os dados de outros bancos que estão contidos no ibdata1 não possuem o seus respectivos diretórios no /var/lib/mysql, apenas ignore estes erros já que você está trabalhando em um sistema de produção, o objetivo aqui é conseguir um dump dos dados do banco que precisa ser recuperado.
O próximo passo então é gerar o dump dos dados com o comando:
mysqldump -uroot -p"senha_de_root" --databases nome_do_banco > dump.sql
Caso o MySQL te retorne erros de conexão ao executar esse comando você deve tentar novamente até conseguir, isso acontece por causa daqueles erros que citei anteriormente pelos bancos que não existem (comigo não foram mais do que duas tentativas).
Bem, é isso ai, agora já temos um arquivo com o dump de todos os dados contidos no banco que precisamos recuperar, basta enviar para o servidor de produção e importar, mas o comando pra fazer isso eu vou deixar como lição de casa!
Um abraço e até a próxima!
Pingback: Recuperando bancos InnoDB no MySQL
#1 by Adilson dos Santos Dantas on June 29th, 2009
| Quote
Tem um jeito de deixar o innodb a moda antiga. no my.cnf adicione a linha “innodb_file_per_table” que os dados não se concentram no idbdata1 e volta a guardar os dados nas pastas.
Por enquanto ainda não tive a oportunidade de recuperar o backup de apenas um banco de dados que tem essa configuração. Mas isso fica por sua conta e risco.
#2 by Patrqiue on June 29th, 2009
| Quote
Valeu Bruno pela dica…
Pingback: Tropeçando 6 | Rafael Bernard Araujo