Jak przekonwertować bazę danych z MyISAM na InnoDB?

9

Zamienię przekonwertować wszystkie tabele bazy danych 500 MB z MyISAM na InnoDB, aby zobaczyć, czy poprawi to ogólną wydajność zajętej witryny Drupal 6. Zastanawiam się, jaki jest najlepszy (tj. Najbezpieczniejszy / najłatwiejszy / najszybszy) sposób wykonania konwersji.

alfish
źródło
To nie wydaje się być pytanie związane z Drupalem, prawda?
tostinni
2
Nie bezpośrednio, ale jest to coś, co administratorzy Drupala muszą czasem robić.
mpdonadio
Zaktualizowałem swoją odpowiedź, aby użyć nowej komendy SQL do odfiltrowania tabel MyISAM, które mają indeksy FULLTEXT. Uruchom ponownie wszystkie kroki od zera, korzystając z mojej zaktualizowanej odpowiedzi.
RolandoMySQLDBA
Jeśli Twoja witryna Drupal nie jest skonfigurowana do wyszukiwania przy użyciu indeksów FULLTEXT, możesz przejść do wszystkich tabel z indeksami FULLTEXT i usunąć te indeksy z tych tabel. Aby znaleźć wszystkie tabele z indeksami FULLTEXT, uruchom SELECT table_schema, table FROM information_schema.statistics WHERE index_type = 'FULLTEXT';
RolandoMySQLDBA

Odpowiedzi:

7

Jako MySQL DBA ufam, że MySQL wykona konwersję, ponieważ MySQL napisze dla mnie skrypt.

Z poziomu polecenia Linux uruchom tę kwerendę

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

Skrypt najpierw skonwertuje najmniejsze tabele. Ten skrypt pominął także wszystkie tabele MyISAM, które mają indeksy FULLTEXT.

Po obejrzeniu skryptu możesz po prostu uruchomić go w MySQL w następujący sposób:

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

lub jeśli chcesz zobaczyć czas każdej konwersji, zaloguj się do mysql i uruchom to:

mysql> source /root/ConvertMyISAM2InnoDB.sql

Nie należy tego pomieszać, ponieważ podczas wykonywania konwersji dochodzi do pełnej blokady tabeli.

Po przekonwertowaniu wszystkich tabel musisz dostroić ustawienia MySQL do użycia InnoDB i przeskalować key_buffer.

Przeczytaj to, aby ustawić pulę buforów InnoDB: /dba/1/what-are-the-main-differences-between-innodb-and-myisam/2194#2194

Przeczytaj również: /drupal/1715/what-would-the-optimal-mysql-configuration-for-a-drupal-7-site-be/2367#2367

Spróbuj !!!

RolandoMySQLDBA
źródło
Roland, wypróbowałem twoje rozwiązanie, ale po zaimportowaniu ConvertMyISAM2InnoDB.sql do bazy danych pojawia się błąd: „BŁĄD 1214 (HY000) w wierszu 585: Używany typ tabeli nie obsługuje indeksów FULLTEXT”. Czy powinienem wiedzieć, czy konwersja miała miejsce w niektórych tabelach i jak mam rozwiązać ten błąd? Dzięki
alfish
Bałem się, że to się stanie. Oznacza to po prostu, że jedna tabela MyISAM miała indeks FULLTEXT. Zaloguj się do mysql i uruchom, jeśli chcesz zobaczyć czas. Innymi słowy, uruchom źródło /root/ConvertMyISAM2InnoDB.sql
RolandoMySQLDBA
Spróbuję zaktualizować skrypt generowania SQL, aby pominąć tabele, które mają indeksy FULLTEXT.
RolandoMySQLDBA
W międzyczasie powtórz wszystkie te kroki od zera. Pierwszy wiersz zregenerowanego pliku zawiera plik MyISAM z indeksem FULLTEXT. Wystarczy usunąć ten pierwszy wiersz i ponownie uruchomić skrypt.
RolandoMySQLDBA
Cóż, uruchamiając ten fajny skrypt konwersji bash ( yoodey.com/… ), zorientowałem się, że najwyraźniej jedyną tabelą w mojej bazie danych, która używa pełnego tekstu, jest „search_index”. Powoduje to zatrzymanie konwersji, ale po anulowaniu konwersji na nim reszta przebiegła bezproblemowo. Uruchamiając źródło ConvertMyISAM2InnoDB.sql, nie mogłem wskazać winowajcy. W każdym razie doceniam twoją pomoc.
Alfish
4

Jakiś czas temu napisałem dla niego drush.

<?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");
  }
}

Pracowałem dla mnie mniej więcej rok temu, nie jestem pewien, czy interfejs API drush zmienił się od tego czasu.

Możesz umieścić to w pliku convert.drush.inc, na przykład w folderze .drush, lub wykonać jakoś na swojej stronie, na przykład za pomocą devel execute block php. Jako skrypt drush, możesz nazwać to tak:

drush convert-engine InnoDB

Ostrzeżenie : jeśli ktoś zrobi coś z bazą danych podczas działania tych poleceń, baza danych zostanie całkowicie pomieszana. Nie do odzyskania. Przed przejściem do tej czynności przejdź do trybu konserwacji i wykonaj kopię zapasową! I oczywiście najpierw wypróbuj stronę deweloperską / testową :)

Berdir
źródło
5
Zgadzam się z Berdir, wykonaj kopię zapasową witryny. Podczas tej operacji baza danych zostanie ZABLOKOWANA. Jeśli chcesz moduł, który może to zrobić, daj DB Tuner szansę.
mikeytown2
@ mikeytown2: To całkiem fajny moduł :)
Berdir
1
Fajny skrypt, ale wydaje się dość przesadny w porównaniu do robienia tego bezpośrednio w kliencie MySQL.
tostinni
2
Skrypt ma dokładnie 5 linii kodu. Resztą jest zintegrowanie go z drush. Można to zrobić za pomocą pojedynczej komendy SQL w MySQL. Tak czy inaczej, to ma napisać scenariusz.
Berdir