Como limpar um mecanismo de armazenamento mysql InnoDB?


133

É possível limpar um mecanismo de armazenamento mysql innodb para que ele não armazene dados de tabelas excluídas?

Ou tenho que reconstruir um banco de dados sempre novo?


O que faz você pensar que o MySQL está armazenando dados de tabelas excluídas?
Robert Munteanu

1
Se eu largar um monte de grandes tabelas, meus arquivos de armazenamento InnoDB não encolher
Bryan Campo

2
@RobertMunteanu: veja bugs.mysql.com/bug.php?id=1341
Max

Respostas:


351

Aqui está uma resposta mais completa em relação ao InnoDB. É um processo um pouco demorado, mas pode valer a pena.

Lembre-se de que esse /var/lib/mysql/ibdata1é o arquivo mais ocupado da infraestrutura do InnoDB. Normalmente, abriga seis tipos de informações:

Arquitetura InnoDB

Arquitetura InnoDB

Muitas pessoas criam vários ibdataarquivos esperando um melhor gerenciamento e desempenho do espaço em disco, no entanto, essa crença está errada.

Posso correr OPTIMIZE TABLE?

Infelizmente, a execução OPTIMIZE TABLEem uma tabela do InnoDB armazenada no arquivo de espaço de tabela compartilhado ibdata1faz duas coisas:

  • Torna os dados e índices da tabela contíguos dentro ibdata1
  • Aumenta ibdata1porque os dados contíguos e as páginas de índice são anexados aibdata1

No entanto, você pode separar os dados da tabela e os índices da tabela ibdata1e gerenciá-los independentemente.

Posso correr OPTIMIZE TABLEcom innodb_file_per_table?

Suponha que você deveria adicionar innodb_file_per_tablea /etc/my.cnf (my.ini). Você pode então rodar OPTIMIZE TABLEem todas as tabelas do InnoDB?

Boas notícias : quando você executa OPTIMIZE TABLEcom innodb_file_per_tableativado, isso produz um .ibdarquivo para essa tabela. Por exemplo, se você tiver uma tabela mydb.mytablecom um dado /var/lib/mysql, ela produzirá o seguinte:

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

O .ibdconterá as páginas de dados e páginas de índice para essa tabela. Ótimo.

Más notícias : tudo o que você fez foi extrair as páginas de dados e as páginas de índice de sua mydb.mytableresidência ibdata. A entrada do dicionário de dados para todas as tabelas, inclusive mydb.mytable, ainda permanece no dicionário de dados (consulte a representação pictórica do ibdata1 ). VOCÊ NÃO PODE APAGAR SIMPLESMENTE ibdata1NESTE PONTO! Observe que ibdata1não encolheu nada.

Limpeza da infraestrutura do InnoDB

Para diminuir de ibdata1uma vez por todas, você deve fazer o seguinte:

  1. Despejar (por exemplo, com mysqldump) todos os bancos de dados em um .sqlarquivo de texto ( SQLData.sqlé usado abaixo)

  2. Elimine todos os bancos de dados (exceto mysqle information_schema) CAVEAT : como precaução, execute este script para garantir que você tenha todas as concessões de usuário em vigor:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
  3. Entre no mysql e execute SET GLOBAL innodb_fast_shutdown = 0;(Isso liberará completamente todas as mudanças transacionais restantes de ib_logfile0e ib_logfile1)

  4. Desligamento do MySQL

  5. Adicione as seguintes linhas ao /etc/my.cnf(ou my.inino Windows)

    [mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G

    (Nota: qualquer que seja o seu objetivo innodb_buffer_pool_size, verifique se innodb_log_file_sizeé 25% de innodb_buffer_pool_size.

    Também: innodb_flush_method=O_DIRECTnão está disponível no Windows)

  6. Excluir ibdata*e ib_logfile*, opcionalmente, você pode remover todas as pastas /var/lib/mysql, exceto /var/lib/mysql/mysql.

  7. Inicie o MySQL (isso irá recriar ibdata1[10 MB por padrão] ib_logfile0e ib_logfile1com 1G cada).

  8. Importar SQLData.sql

Agora, ibdata1ainda crescerá, mas conterá apenas metadados da tabela, porque cada tabela InnoDB existirá fora de ibdata1. ibdata1não conterá mais dados e índices do InnoDB para outras tabelas.

Por exemplo, suponha que você tenha uma tabela InnoDB denominada mydb.mytable. Se você olhar /var/lib/mysql/mydb, verá dois arquivos representando a tabela:

  • mytable.frm (Cabeçalho do mecanismo de armazenamento)
  • mytable.ibd (Dados e índices da tabela)

Com a innodb_file_per_tableopção ativada /etc/my.cnf, você pode executar OPTIMIZE TABLE mydb.mytablee o arquivo /var/lib/mysql/mydb/mytable.ibddiminuirá.

Eu já fiz isso muitas vezes na minha carreira como DBA do MySQL. De fato, na primeira vez que fiz isso, reduzi um arquivo de 50 GB ibdata1 para apenas 500 MB!

De uma chance. Se você tiver mais perguntas sobre isso, basta perguntar. Confie em mim; isso funcionará a curto prazo e a longo prazo.

EMBARGO

Na Etapa 6, se o mysql não puder reiniciar devido ao mysqlinício do esquema, olhe para a Etapa 2. Você fez a cópia física do mysqlesquema. Você pode restaurá-lo da seguinte maneira:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

Volte para a Etapa 6 e continue

UPDATE 2013-06-04 11:13 EDT

No que diz respeito à configuração de innodb_log_file_size para 25% de innodb_buffer_pool_size na Etapa 5, essa regra geral é bastante antiga.

De volta July 03, 2006, a Percona tinha um bom artigo sobre por que escolher um tamanho innodb_log_file_size adequado . Posteriormente, a Nov 21, 2008Percona acompanhou outro artigo sobre como calcular o tamanho adequado com base no pico de carga de trabalho, mantendo as alterações de uma hora .

Desde então, escrevi postagens no DBA StackExchange sobre o cálculo do tamanho do log e onde referenciei esses dois artigos da Percona.

Pessoalmente, eu continuaria com a regra de 25% para uma configuração inicial. Então, como a carga de trabalho pode ser determinada com mais precisão ao longo do tempo na produção, você pode redimensionar os logs durante um ciclo de manutenção em apenas alguns minutos.


9
Também usei a opção innodb_file_per_table com grande efeito: tendo 200 bancos de dados com 200 tabelas cada em um único servidor, consegui desvincular bancos de dados de diferenças em diferentes partições, usando mais buffers e eixos de E / S que, de outra forma, estariam disponíveis :)
Dave Rix

2
@SeanDowney BTW lembre- innodb_open_tablesse de aumentar, se necessário. O padrão é 300.
RolandoMySQLDBA

2
@ giorgio79, você precisa definir sua inserção em massa para um valor maior. Este é um bom argumento. Acrescentarei a essência da sua pergunta à minha resposta.
RolandoMySQLDBA

3
Em sistemas de 32 bits, um valor de 4Gb para innodb_buffer_pool_size não é permitido. O MySQL começará silenciosamente com o innodb desativado e as tabelas restauradas serão alteradas para myisam. Use um valor um pouco menor para corrigi-lo.
David

5
Bom Deus. Eu só quero dizer que esta é talvez uma das melhores respostas que eu já vi no ótimo trabalho, senhor. Ajudou-me a encontrar uma solução para o meu problema quando estava recebendo um ERRO 2013 (HY000) ao importar um 154g db. Obrigado pela excelente resposta!
Josh Brown

4

O mecanismo do InnoDB não armazena dados excluídos. À medida que você insere e exclui linhas, o espaço não utilizado fica alocado nos arquivos de armazenamento do InnoDB. Com o tempo, o espaço geral não diminuirá, mas com o tempo o espaço 'excluído e liberado' será reutilizado automaticamente pelo servidor do banco de dados.

Você pode ajustar e gerenciar ainda mais o espaço usado pelo mecanismo por meio de uma reorganização manual das tabelas. Para fazer isso, despeje os dados nas tabelas afetadas usando o mysqldump, descarte as tabelas, reinicie o serviço mysql e recrie as tabelas dos arquivos de despejo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.