MySQL InnoDB não liberando espaço em disco após excluir linhas de dados da tabela

140

Eu tenho uma tabela MySQL usando o mecanismo de armazenamento InnoDB; contém cerca de 2 milhões de linhas de dados. Quando excluí as linhas de dados da tabela, ele não libera espaço em disco alocado. O tamanho do arquivo ibdata1 também não foi reduzido após a execução do optimize tablecomando.

Existe alguma maneira de recuperar espaço em disco do MySQL?

Estou em uma situação ruim; esse aplicativo está sendo executado em cerca de 50 locais diferentes e agora o problema de pouco espaço em disco está aparecendo em quase todos eles.

Sumit Deo
fonte
depois de executar o comando optimize também, o tamanho do arquivo ibdata1 não foi reduzido.
Sumit Deo
4
Eu acho que esse comentário seria melhor editado em sua resposta e, em seguida, excluído
Ben Millwood
possível duplicado de stackoverflow.com/q/11751792/82114 (mas esta foi aqui em primeiro lugar)
FlipMcF
1
"O tamanho do arquivo ibdata1 também não foi reduzido após a execução do comando optimize table" porque o seu innodb_file_per_tableestá desativado. A boa notícia é que essa opção é onpor padrão nas versões recentes do MySQL.
Contador م
Eu corro "otimizar tabela xxxx" e recebi a mensagem "A tabela não suporta otimizar, ao invés disso, recriar + analisar". Depois de executar "du -h / var / lib / mysql" em um shell, pude ver que o banco de dados havia encolhido.
user1097111 10/07

Respostas:

137

O MySQL não reduz o tamanho do ibdata1. Sempre. Mesmo se você usar optimize tablepara liberar o espaço usado nos registros excluídos, ele será reutilizado posteriormente.

Uma alternativa é configurar o servidor para uso innodb_file_per_table, mas isso exigirá um backup, descarte do banco de dados e restauração. O lado positivo é que o arquivo .ibd da tabela é reduzido após um optimize table.

Leonel Martins
fonte
4
Documentos do MySQL 5.5 sobre o estado do modo arquivo por tabela do InnoDB "Para tirar proveito dos recursos [arquivo por tabela do InnoDB] para uma tabela existente, você pode ativar a configuração de arquivo por tabela e executar ALTER TABLE t ENGINE=INNODBna tabela existente. " Isso implica que você pode ativar esse recurso, "converter" as tabelas existentes para usar um arquivo InnoDB separado com o comando ALTER TABLE e, em seguida, OTIMIZAR a tabela para diminuir seu tamanho. No entanto, quando você estiver pronto você tem que descobrir como excluir o (enorme) arquivo InnoDB fonte ...
Josh
9
Eu acho que isso responde tecnicamente à pergunta, mas eu esperaria que a maioria das pessoas pesquisando neste tópico esteja procurando pelo processo real para reduzir / recuperar o espaço, o que esta resposta não fornece.
Manachi
@Manachi O processo é "configurar o servidor para usar innodb_file_per_table", "fazer backup" do servidor ", soltar o banco de dados", parar o mysql, excluir .ibd, iniciar o servidor e restaurar o banco de dados. Com o MySQL 5.5+, você pode usar o que Josh disse e, após alterar todas as tabelas, parar o servidor, excluir o enorme .ibd e iniciá-lo novamente.
Leonel Martins
39

Só tive o mesmo problema.

O que acontece é que, mesmo se você soltar o banco de dados, o innodb ainda não liberará espaço em disco. Eu tive que exportar, parar o mysql, remover os arquivos manualmente, iniciar o mysql, criar banco de dados e usuários e depois importar. Graças a Deus eu só tinha 200 MB de linhas, mas poupou 250 GB de arquivo innodb.

Falhar por design.

gilm
fonte
10
Sim, isso é definitivamente um fracasso.
trusktr
1
O MySql 5.5 tem o mesmo problema: executei "otimizar tabela" para reduzir o uso de disco de uma tabela de 28 GB. A operação provavelmente tentou criar um clone otimizado do original e, dessa forma, consumiu todo o espaço da partição. Agora, "otimizar tabela" falhou e fiquei sem espaço na partição, mesmo depois de deixar cair o banco de dados inteiro ... muito decepcionante.
precisa
1
E mais de quatro anos depois, tive o mesmo problema com o MySQL. O MS SQL é semelhante: dba.stackexchange.com/questions/47310/…
Csaba Toth
24

Se você não usar innodb_file_per_table , é possível recuperar espaço em disco, mas é muito tedioso e requer uma quantidade significativa de tempo de inatividade.

O How To é bastante aprofundado - mas colei a parte relevante abaixo.

Também mantenha uma cópia do seu esquema no seu dump.

Atualmente, você não pode remover um arquivo de dados do espaço de tabela do sistema. Para diminuir o tamanho do espaço de tabela do sistema, use este procedimento:

Use o mysqldump para despejar todas as suas tabelas do InnoDB.

Pare o servidor.

Remova todos os arquivos de espaço de tabela existentes, incluindo os arquivos ibdata e ib_log. Se você deseja manter uma cópia de segurança das informações, copie todos os arquivos ib * para outro local antes de remover os arquivos em sua instalação do MySQL.

Remova todos os arquivos .frm das tabelas do InnoDB.

Configure um novo espaço de tabela.

Reinicie o servidor.

Importe os arquivos de despejo.

FlipMcF
fonte
Obrigado por incluir os passos. Afinal, o link 'como fazer' não contém mais essas informações
aland
3

Dez anos depois e eu tive o mesmo problema. Eu resolvi da seguinte maneira:

  • Otimizei todos os bancos de dados restantes.
  • Reiniciei meu computador e o MySQL nos serviços (Windows + r -> services.msc)

Isso é tudo :)

Matheus Douglas
fonte
1

Outra maneira de resolver o problema da recuperação de espaço é: criar várias partições dentro da tabela - Partições baseadas em intervalo, baseadas em valor e simplesmente soltar / truncar a partição para recuperar o espaço, o que liberará o espaço usado por dados inteiros armazenados na partição específica.

Haverá algumas alterações necessárias no esquema da tabela quando você introduzir o particionamento para sua tabela como - Chaves Exclusivas, Índices para incluir a coluna da partição etc.

Anand Immannavar
fonte
0

No ano passado, eu também enfrentei o mesmo problema na versão mysql5.7 e o ibdata1 ocupava 150 Gb. então eu adicionei desfazer espaços de tabela

Tome backup do Mysqldump
Pare o serviço mysql
Remova todos os dados do diretório de dados
Adicione abaixo do parâmetro de espaço de tabela desfazer no my.cnf atual

 #undo tablespace
  innodb_undo_directory =  /var/lib/mysql/
  innodb_rollback_segments = 128 
  innodb_undo_tablespaces = 3
  innodb_undo_logs = 128  
  innodb_max_undo_log_size=1G
  innodb_undo_log_truncate = ON

Iniciar o mysql service
store mysqldump backup

Problema resolvido !!

Gajendra
fonte
-1

Existem várias maneiras de recuperar o espaço em disco após excluir os dados da tabela para o mecanismo MySQL Inodb

Se você não usa innodb_file_per_table desde o início, despejar todos os dados, excluir todos os arquivos, recriar banco de dados e importar dados novamente é apenas uma maneira (verifique as respostas do FlipMcF acima)

Se você estiver usando innodb_file_per_table, tente

  1. Se você puder excluir todos os dados, o comando truncar excluirá os dados e recuperará o espaço em disco para você.
  2. O comando Alter table irá soltar e recriar a tabela para recuperar o espaço em disco. Portanto, após excluir dados, execute alter table que não altera nada para liberar o disco rígido (ou seja: tabela TBL_A possui charset uf8, após excluir dados, execute ALTER TABLE TBL_A charset utf8 -> esse comando não altera nada da sua tabela, mas faz o mysql recriar sua tabela e recuperar espaço em disco
  3. Crie TBL_B como TBL_A. Insira os dados selecionados que você deseja manter de TBL_A em TBL_B. Solte TBL_A e renomeie TBL_B para TBL_A. Dessa forma, é muito eficaz se o TBL_A e os dados necessários para excluir forem grandes (o comando delete no MySQL innodb apresenta desempenho muito ruim)
Bùi Đức Khánh
fonte