Como faço para converter um banco de dados do MyISAM para o InnoDB?

9

Vou converter todas as tabelas do banco de dados de 500 MB do MyISAM para o InnoDB para ver se ele melhorará o desempenho geral de um site do Drupal 6 ocupado. Gostaria de saber qual é a melhor maneira (ou seja, mais segura / mais fácil / mais rápida) de fazer a conversão.

alfish
fonte
Isso não parece ser uma pergunta relacionada ao Drupal, não é?
tostinni
2
Não diretamente, mas é algo que os administradores do Drupal precisam fazer ocasionalmente.
mpdonadio
Atualizei minha resposta para usar um novo comando SQL para filtrar as tabelas MyISAM que possuem índices FULLTEXT. Execute novamente todas as etapas do zero usando minha resposta atualizada.
RolandoMySQLDBA
Se o seu site Drupal não estiver configurado para pesquisar usando índices FULLTEXT, convém ir a todas as tabelas com índices FULLTEXT e eliminá-los dessas tabelas. Para localizar todas as tabelas com índices FULLTEXT, execute SELECT table_schema, tabela FROM information_schema.statistics WHERE index_type = 'FULLTEXT';
RolandoMySQLDBA

Respostas:

7

Como DBA do MySQL, confio no MySQL para fazer a conversão, fazendo com que o MySQL escreva o script para mim.

Forme o comando Linux, execute esta consulta

mysql -h... -u... -p... -A --skip-column-names -e"SELECT CONCAT('ALTER TABLE ',db,'.',tb,' ENGINE=InnoDB;') FROM (SELECT A.db,A.tb,A.tbsize FROM (SELECT table_schema db,table_name tb,(data_length+index_length) tbsize FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql')) A LEFT JOIN (SELECT table_schema db,table_name tb FROM information_schema.statistics WHERE index_type='FULLTEXT') B USING (db,tb) WHERE B.db IS NULL) AA ORDER BY tbsize" > /root/ConvertMyISAM2InnoDB.sql

O script converterá as tabelas menores primeiro. Esse script também ignorou as tabelas MyISAM que possuem índices FULLTEXT.

Depois de examinar o script, você pode simplesmente executá-lo no MySQL da seguinte maneira:

mysql -h... -u... -p... -A < /root/ConvertMyISAM2InnoDB.sql

ou se você quiser ver o tempo de cada conversão, entre no mysql e execute:

mysql> source /root/ConvertMyISAM2InnoDB.sql

Isso não deve ser confuso, porque um bloqueio de tabela completo acontece quando a conversão está sendo executada.

Depois que todas as tabelas forem convertidas, você precisará ajustar as configurações do MySQL para uso do InnoDB e reduzir o key_buffer.

Leia isso para configurar o InnoDB Buffer Pool: /dba/1/what-are-the-main-differences-between-innodb-and-myisam/2194#2194

Leia também: /drupal/1715/what-would-the-optimal-mysql-configuration-for-a-drupal-7-site-be/2367#2367

De uma chance !!!

RolandoMySQLDBA
fonte
Roland, tentei sua solução, mas depois de importar o ConvertMyISAM2InnoDB.sql para o banco de dados, recebo este erro: "ERRO 1214 (HY000) na linha 585: O tipo de tabela usado não suporta índices FULLTEXT". Então, devo saber se a conversão ocorreu em algumas tabelas e como devo resolver esse erro? Graças
alfish
Eu tinha medo que isso acontecesse. Significa simplesmente que uma tabela MyISAM tinha um índice FULLTEXT. Faça o login no mysql e execute se quiser ver o tempo. Em outras palavras, execute source /root/ConvertMyISAM2InnoDB.sql
RolandoMySQLDBA
Vou tentar atualizar o script de geração SQL para ignorar as tabelas que possuem índices FULLTEXT.
RolandoMySQLDBA
Enquanto isso, repita todas essas etapas do zero. A primeira linha do arquivo regenerado possui o arquivo MyISAM com o índice FULLTEXT. Simplesmente exclua a primeira linha e execute novamente o script.
RolandoMySQLDBA
Bem, executando esse script bacana de conversão ( yoodey.com/… ), descobri que aparentemente a única tabela no meu banco de dados que usa Texto Completo é 'search_index'. Isso causou a interrupção da conversão, mas depois de cancelar a conversão, o restante continuou sem problemas. Ao executar o ConvertMyISAM2InnoDB.sql de origem, não consegui identificar o culpado. De qualquer forma, agradeço a sua ajuda.
alfish
4

Eu escrevi um comando drush para isso há um tempo atrás.

<?php
/**
 * Implements hook_drush_command().
 */
function convert_drush_command() {
  $items = array();

  // the key in the $items array is the name of the command.
  $items['convert-engine'] = array(
    // a short description of your command
    'description' => "Convert MYSQL Table Type",
  );
  return $items;
}

function drush_convert_engine() {
  $args = func_get_args();
  $engine = $args[0];

  $result = db_query("SHOW TABLES");
  while ($row = db_fetch_array($result)) {
    $table = array_shift($row);
    drush_log(dt('Converting @table to @engine', array('@table' => $table, '@engine' => $engine)), 'success');
    db_query("ALTER TABLE $table ENGINE = $engine");
  }
}

Trabalhou para mim há um ano, mais ou menos, não tenho certeza se a API drush mudou desde então.

Você pode colocar isso em um convert.drush.inc, por exemplo, na pasta .drush ou executá-lo de alguma forma no seu site, por exemplo, com o bloco devel execute php. Como um script drush, você pode chamar assim:

drush convert-engine InnoDB

Aviso : Se alguém fizer algo com o banco de dados enquanto esses comandos são executados, seu banco de dados será completamente destruído. Irrecuperavelmente. Portanto, coloque seu site no modo de manutenção e faça um backup antes de tentar isso! E, é claro, tente primeiro um site de desenvolvimento / teste :)

Berdir
fonte
5
Concorde com o Berdir, faça backup do seu site. Enquanto esta operação estiver em andamento, seu banco de dados será BLOQUEADO. Se você deseja um módulo que possa fazer isso, experimente o DB Tuner .
mikeytown2
@ mikeytown2: Isso é um módulo legal pretty :)
Berdir
1
Bom script, mas parece um exagero em relação a fazer isso diretamente no cliente MySQL.
tostinni
2
O script é exatamente 5 linhas de código. O resto é integrá-lo ao drush. Existe uma maneira de fazer isso em um único comando sql no MySQL. De uma forma ou de outra, você precisa escrever um script.
Berdir