MySql - alterando innodb_file_per_table para um db ao vivo

18

Eu tenho um grande banco de dados MySql (150 GB) e só agora notei que o innodb_file_per_tableestá configurado para fazer com offque todo o banco de dados seja hospedado em um único arquivo ( ibdata1). Quero ativar innodb_file_per_tablee dividir o banco de dados retroativamente em vários arquivos. Qual é a melhor maneira de fazer isso?

Correu
fonte

Respostas:

32

Existe realmente apenas uma maneira de conseguir isso. Você terá que exportar os dados usando o mysqldumps, descartar todos os bancos de dados, desligar o mysqld, excluir ib_logfile0, excluir ib_logfile1, excluir ib_logfile1, excluir ibdata1, adicionar innodb_file_per_tablesob o [mysqld]cabeçalho, iniciar o mysql.

Publiquei esta resposta no StackOverflow em outubro de 2010

Aqui estão as etapas listadas verticalmente:

Etapa 01) MySQLDump todos os bancos de dados em um arquivo de texto SQL (chame-o SQLData.sql)

Etapa 02) Solte todos os bancos de dados (exceto o esquema mysql)

Etapa 03) Desligar o mysql

CAVEAT : Para limpar totalmente transações não confirmadas dos arquivos InnoDB, execute este

mysql -uroot -p... -Ae"SET GLOBAL innodb_fast_shutdown = 0;"
service mysql stop

Etapa 04) Adicione as seguintes linhas ao /etc/my.cnf

[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 conjunto para innodb_buffer_pool_size, verifique se innodb_log_file_size é 25% de innodb_buffer_pool_size.

Etapa 05) Excluir ibdata1, ib_logfile0 e ib_logfile1

Neste ponto, deve haver apenas o esquema mysql em / var / lib / mysql

Etapa 06) Reinicie o mysql

Isso recriará ibdata1 em 10 MB, ib_logfile0 e ib_logfile1 em 1G cada

Etapa 07) Recarregar SQLData.sql no mysql

ibdata1 crescerá, mas conterá apenas metadados da tabela

Cada tabela do InnoDB existirá fora do ibdata1

Suponha que você tenha uma tabela do InnoDB chamada mydb.mytable. Se você acessar / var / lib / mysql / mydb, verá dois arquivos representando a tabela

  • mytable.frm (cabeçalho do mecanismo de armazenamento)
  • mytable.ibd (Página inicial dos dados e índices da tabela para mydb.mytable)

O ibdata1 nunca mais conterá dados e índices do InnoDB.

Com a opção innodb_file_per_table em /etc/my.cnf, você pode executar o OPTIMIZE TABLE mydb.mytable e o arquivo /var/lib/mysql/mydb/mytable.ibd realmente diminuirá.

Eu fiz isso muitas vezes na minha carreira como DBA MySQL

De fato, na primeira vez em que fiz isso, reduzi um arquivo ibdata1 de 50 GB em 500 MB.

De uma chance. Se você tiver mais perguntas sobre isso, envie-me um e-mail. Confie em mim. Isso funcionará a curto prazo e a longo prazo. !!!

Existe uma alternativa que extrairá a tabela InnoDB sem reduzir o ibdata1.

Etapa 01) Adicione as seguintes linhas ao /etc/my.cnf

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

Etapa 02) service mysql restart

Etapa 03) Para extrair uma única tabela do InnoDB chamada mydb.mytable, faça o seguinte:

ALTER TABLE mydb.mytable ENGINE=InnoDB;

Isso criará um arquivo pleus manter o arquivo de estrutura original

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

Você pode fazer isso para todas as tabelas do InnoDB. Infelizmente, o ibdata1 ficará com 150 GB.

RolandoMySQLDBA
fonte
durante a execução do recarregamento dos arquivos .sql, recebi o seguinte erro, ERROR 1071 (42000) at line 25: Specified key was too long; max key length is 1000 bytesalguma idéia?
Ran
@Ran, por favor, poste isso como uma pergunta separada.
RolandoMySQLDBA 23/01
Se você configurar innodb_file_per_tablee, em seguida, fizer isso ALTER TABLEem todas as tabelas, será possível excluir o arquivo ibdata1 para recuperar o espaço sem precisar restaurar?
precisa
11
@SystemParadox ABSOLUTAMENTE NÃO !!!!!!!! Você perderá o dicionário de dados.
RolandoMySQLDBA
5

Se você deseja recuperar o espaço do ibdata, uma despejo / restauração é sua única opção, como aponta Rolando . Também é provavelmente o melhor desempenho para fazer isso.

No entanto, se você quiser apenas reduzir suas perdas e "perder" esses 150 GB no disco rígido, basta ativar innodb_file_per_tableo my.cnf e reiniciar o servidor.

Em seguida, para cada tabela, emita:

ALTER TABLE x DISABLE KEYS;
ALTER TABLE x ENGINE=InnoDB;
ALTER TABLE x ENABLE KEYS; 

O problema aqui é que espaços de tabela grandes levarão um tempo.

O que eu sugeriria é configurar um escravo do seu banco de dados ao vivo, executar a conversão no escravo, desligar o mestre / escravo e copiar o novo espaço de dados para o mestre, ou promover o escravo para ser o mestre depois de capturado .

Você terá dificuldade em fazer essa alteração sem tempo de inatividade.

Derek Downey
fonte
+1 por ser brutalmente honesto e dizer "reduza suas perdas". Você poderia ter dito 'morda a bala' também.
RolandoMySQLDBA 20/01/12
Você pode usar pt-online-schema-change para evitar o tempo de inatividade ao executar a tabela de alteração.
cornernote