MySQL InnoDB perdeu tabelas mas existem arquivos

33

Eu tenho um MySQL InnoDB que possui todos os arquivos de tabela do banco de dados, mas o MySQL não os vê e não os carrega.

O problema aconteceu porque eu apaguei esses três arquivos: ibdata1, ib_logfile0eib_logfile1

porque eu estava tendo problemas com o mysql inicializando, e o que li foi para removê-los porque o MySQL apenas os regenerará (eu sei que eu deveria ter feito o backup deles, mas não o fiz).

O que posso fazer para que o MySQL veja as tabelas novamente?

about_member.frm                              site_stories.frm
about_member.ibd                              site_stories.ibd
db.opt                                        stories.frm
FTS_00000000000000bb_BEING_DELETED_CACHE.ibd  stories.ibd
FTS_00000000000000bb_BEING_DELETED.ibd        story_comments.frm
FTS_00000000000000bb_CONFIG.ibd               story_comments.ibd
FTS_00000000000000bb_DELETED_CACHE.ibd        story_likes.frm
FTS_00000000000000bb_DELETED.ibd              story_likes.ibd
FTS_00000000000000f5_BEING_DELETED_CACHE.ibd  story_tags.frm
FTS_00000000000000f5_BEING_DELETED.ibd        story_tags.ibd
FTS_00000000000000f5_CONFIG.ibd               story_views.frm
FTS_00000000000000f5_DELETED_CACHE.ibd        story_views.ibd
FTS_00000000000000f5_DELETED.ibd              story_view_totals.frm
member_favorites.frm                          story_view_totals.ibd
member_favorites.ibd                          tags.frm
members.frm                                   tags.ibd
members.ibd
Saia do meu gramado
fonte
Você tentou restaurar esses arquivos? Os arquivos de log podem permanecer excluídos. Você realmente não deveria ter excluído ibdata1
Ramhound 13/11
Copiei o arquivo de uma versão antiga do mysql onde o arquivo estava localizado, mas as tabelas não aparecem.
Get Off My Lawn

Respostas:

36

Aqui está o porquê o MySQL não pode ver esses arquivos: O espaço de tabela do sistema (ibdata1) possui um dicionário de dados específico do Storage-Engine que permite ao InnoDB mapear o uso potencial da tabela:

Arquitetura InnoDB

Mover tabelas do InnoDB de um lugar para outro requer comandos como

ALTER TABLE tblname DISCARD TABLESPACE;
ALTER TABLE tblname IMPORT TABLESPACE;

Aqui está uma parte da documentação do MySQL 5.5, explicando o que precisa ser considerado

Considerações sobre portabilidade para arquivos .ibd

Você não pode mover livremente os arquivos .ibd entre os diretórios do banco de dados, como é possível com os arquivos de tabela MyISAM. A definição de tabela armazenada no espaço de tabela compartilhado do InnoDB inclui o nome do banco de dados. Os IDs da transação e os números de sequência do log armazenados nos arquivos do espaço de tabela também diferem entre os bancos de dados.

Para mover um arquivo .ibd e a tabela associada de um banco de dados para outro, use uma instrução RENAME TABLE:

TABELA DE RENOMEAÇÃO db1.tbl_name TO db2.tbl_name; Se você tiver um backup "limpo" de um arquivo .ibd, poderá restaurá-lo para a instalação do MySQL da qual se originou da seguinte maneira:

A tabela não deve ter sido descartada ou truncada desde que você copiou o arquivo .ibd, pois isso altera o ID da tabela armazenada dentro do espaço de tabela.

Emita esta instrução ALTER TABLE para excluir o arquivo .ibd atual:

ALTER TABLE nome_tabela DISCARD TABLESPACE; Copie o arquivo .ibd de backup no diretório de banco de dados apropriado.

Emita esta instrução ALTER TABLE para informar ao InnoDB para usar o novo arquivo .ibd da tabela:

ALTER TABLE nome_tabela IMPORT TABLESPACE; Nesse contexto, um backup de arquivo .ibd “limpo” é aquele para o qual os seguintes requisitos são atendidos:

Não há modificações não confirmadas por transações no arquivo .ibd.

Não há entradas de buffer de inserção não imersas no arquivo .ibd.

A remoção removeu todos os registros de índice marcados com exclusão do arquivo .ibd.

O mysqld liberou todas as páginas modificadas do arquivo .ibd do buffer pool para o arquivo.

Dadas essas advertências e protocolos, aqui está um curso de ação sugerido

Neste exemplo, vamos tentar restaurar a tagstabela no mydbbanco de dados

PASSO 1

Verifique se você tem backups daqueles .frme .ibdarquivos/tmp/innodb_data

PASSO 2

Obtenha a CREATE TABLE tagsinstrução e execute-a como CREATE TABLE mydb.tags .... Verifique se é exatamente a mesma estrutura que o originaltags.frm

ETAPA 3

Exclua o vazio tags.ibdusando o MySQL

ALTER TABLE mydb.tags DISCARD TABLESPACE;

PASSO 4

Traga a cópia de backup de tags.ibd

cd /var/lib/mysql/mydb
cp /tmp/innodb_data.tags.ibd .
chown mysql:mysql tags.ibd

PASSO # 5

Adicionar tagstabela ao dicionário de dados do InnoDB

ALTER TABLE mydb.tags IMPORT TABLESPACE;

PASSO 6

Teste a acessibilidade da tabela

SHOW CREATE TABLE mydb.tags\G
SELECT * FROM mydb.tags LIMIT 10;

Se você obtiver resultados normais, parabéns por importar uma tabela do InnoDB.

PASSO 7

No futuro, não exclua ibdata1 e seus logs

De uma chance !!!

Eu já discuti coisas assim antes

EMBARGO

E se você não conhece a estrutura da tabela do tags?

Existem ferramentas para obter a instrução CREATE TABLE apenas usando o .frmarquivo Também escrevi um post sobre isso: como extrair o esquema da tabela apenas do arquivo .frm? . Nesse post, copiei um arquivo .frm para uma máquina Windows a partir de uma caixa Linux, executei a ferramenta Windows e obtive a CREATE TABLEdeclaração.

RolandoMySQLDBA
fonte
Obrigado pela incrível resposta! Ainda estou importando uma tabela, porque continuo criando problemas, mas chegarei lá eventualmente e informarei como funciona! Obrigado!
Get Off My Lawn
1
Quando executo a criação, recebo: ERRO 1813 (HY000): espaço de tabela para tabela ' weblyize. tags' existe. DESCARTE o espaço de tabela antes de IMPORTAR. Então, tento executar o alter tablespace primeiro e recebo este erro: ERRO 1146 (42S02): A tabela 'weblyize.tags' não existe . O que eu posso fazer?
Get Off My Lawn
Obrigado! Para corrigir meu erro, criei um novo banco de dados, executei CREATE TABLE ...e siga suas etapas! Você me salvou de ter que reescrevê-los 100% do zero! Não importou chaves estrangeiras, mas tudo bem, eu mesmo posso fazer isso! Mais uma vez obrigado!
Get Off My Lawn
E se eu tiver 100 tabelas que devem ser corrigidas dessa maneira. Não farei operações para cada mesa manualmente. Como poderia ser automatizado?
Oleg Abrazhaev 29/11
10

Eu tenho a mesma situação, não é possível soltar ou criar tblname específico. Meu procedimento de correção é:

  1. Pare o MySQL.

    service mysql stop
    
  2. Remova ib_logfile0 e ib_logfile1.

    cd /var/lib/mysql;
    rm ib_logfile0 ib_logfile1
    
  3. Remova os arquivos tblname. AVISO: ESTE DECLARARÁ SEMPRE SEUS DADOS

    cd /var/lib/mysql/dbname;
    rm tblname*
    
  4. Inicie o MySQL.

    service mysql start
    
user293871
fonte
1
Obrigado, isso resolveu meu problema, não fiz a etapa 3, simplesmente removi os arquivos de log e iniciei o backup do mysql.
Jeff Wilbert
Você é absolutamente fantástico! Resolvido meu problema.
Alex GP #
2

Eu tive esse problema também. Apaguei ibdata1acidentalmente e todos os meus dados foram perdidos.

Após uma pesquisa de um dia no google e no SO, finalmente encontrei uma solução que salvou minha vida (eu tinha tantos bancos de dados e tabelas com registros enormes).

  1. faça um backup de /var/lib/mysql

  2. recuperar esquema da tabela do .frmarquivo com dbsake (havia outra opção! mysqlfrm . mas não funcionou para mim)

dbsake frmdump --type-codes /var/lib/mysql/database-name/tbl.frm
  1. crie nova tabela (com novo nome) com esquema exportado.

  2. descarte novos dados da tabela com este comando:

ALTER TABLE `tbl-new` DISCARD TABLESPACE;
  1. copie os dados da tabela antiga e cole-os em vez de novos e defina a permissão correta.
cp tbl.ibd [email protected] && chown mysql:mysql [email protected]
  1. importar dados para nova tabela.
ALTER TABLE `tbl-new` IMPORT TABLESPACE;
  1. bem! temos dados na nova tabela e podemos abandonar a antiga.
DROP TABLE `tbl`;
  1. verifique /var/lib/mysql/database-namee, se houver dados ( .ibdarquivo) para a tabela antiga, exclua-a.
rm tbl.ibd
  1. e finalmente renomeie a nova tabela para o nome original
ALTER TABLE `tbl-new` RENAME `tbl`;
mostafaznv
fonte