Wie konvertiere ich eine Datenbank von MyISAM nach InnoDB?

9

Ich werde alle Tabellen der 500-MB-Datenbank von MyISAM in InnoDB konvertieren, um festzustellen, ob dadurch die Gesamtleistung einer ausgelasteten Drupal 6-Site verbessert wird. Ich frage mich, was der beste (dh sicherste / einfachste / schnellste) Weg ist, um die Konvertierung durchzuführen.

Alfish
quelle
Dies scheint keine Drupal-bezogene Frage zu sein, oder?
Tostinni
2
Nicht direkt, aber es ist etwas, was Drupal-Administratoren gelegentlich tun müssen.
mpdonadio
Ich habe meine Antwort aktualisiert, um mithilfe eines neuen SQL-Befehls MyISAM-Tabellen mit FULLTEXT-Indizes herauszufiltern. Bitte führen Sie alle Schritte mit meiner aktualisierten Antwort von Grund auf neu aus.
RolandoMySQLDBA
Wenn Ihre Drupal-Site nicht für die Suche mit FULLTEXT-Indizes konfiguriert ist, möchten Sie möglicherweise zu allen Tabellen mit FULLTEXT-Indizes wechseln und diese Indizes aus diesen Tabellen löschen. Um alle Tabellen mit FULLTEXT-Indizes zu finden, führen Sie SELECT table_schema, table FROM information_schema.statistics WHERE index_type = 'FULLTEXT' aus.
RolandoMySQLDBA

Antworten:

7

Als MySQL-DBA vertraue ich darauf, dass MySQL die Konvertierung durchführt, indem MySQL das Skript für mich schreibt.

Führen Sie mit dem Linux-Befehl diese Abfrage aus

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

Das Skript konvertiert zuerst die kleinsten Tabellen. Dieses Skript hat auch alle MyISAM-Tabellen mit FULLTEXT-Indizes umgangen.

Nachdem Sie sich das Skript angesehen haben, können Sie es einfach wie folgt in MySQL ausführen:

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

oder wenn Sie den Zeitpunkt jeder Konvertierung sehen möchten, melden Sie sich bei mysql an und führen Sie Folgendes aus:

mysql> source /root/ConvertMyISAM2InnoDB.sql

Dies sollte nicht durcheinander gebracht werden, da bei der Ausführung der Konvertierung eine vollständige Tabellensperre auftritt.

Sobald alle Tabellen konvertiert sind, müssen Sie die MySQL-Einstellungen für die InnoDB-Verwendung optimieren und den key_buffer verkleinern.

Bitte lesen Sie dies, um den InnoDB-Pufferpool festzulegen: /dba/1/what-are-the-main-differences-between-innodb-and-myisam/2194#2194

Bitte lesen Sie dies auch: /drupal/1715/what-would-the-optimal-mysql-configuration-for-a-drupal-7-site-be/2367#2367

Versuche es !!!

RolandoMySQLDBA
quelle
Roland, ich habe Ihre Lösung ausprobiert, aber nach dem Importieren von ConvertMyISAM2InnoDB.sql in die Datenbank wird folgende Fehlermeldung angezeigt: "FEHLER 1214 (HY000) in Zeile 585: Der verwendete Tabellentyp unterstützt keine FULLTEXT-Indizes". Sollte ich also wissen, ob die Konvertierung für einige Tabellen stattgefunden hat und wie ich diesen Fehler beheben soll? Danke
Alfish
Ich hatte Angst, dass das passieren würde. Dies bedeutet einfach, dass eine MyISAM-Tabelle einen FULLTEXT-Index hatte. Melden Sie sich bei MySQL an und führen Sie es aus, wenn Sie das Timing sehen möchten. Mit anderen Worten, führen Sie source /root/ConvertMyISAM2InnoDB.sql
RolandoMySQLDBA
Ich werde versuchen, das SQL-Generierungsskript zu aktualisieren, um Tabellen mit FULLTEXT-Indizes zu überspringen.
RolandoMySQLDBA
Wiederholen Sie in der Zwischenzeit alle diese Schritte von Grund auf. Die erste Zeile der neu generierten Datei enthält die MyISAM-Datei mit dem FULLTEXT-Index. Löschen Sie einfach diese erste Zeile und führen Sie das Skript erneut aus.
RolandoMySQLDBA
Durch Ausführen dieses coolen Conversion-Bash-Skripts ( yoodey.com/… ) habe ich herausgefunden, dass anscheinend die einzige Tabelle in meiner Datenbank, die Volltext verwendet, 'search_index' ist. Dies führte dazu, dass die Konvertierung angehalten wurde, aber nachdem die Konvertierung abgebrochen wurde, verlief der Rest reibungslos. Durch Ausführen der Quelle ConvertMyISAM2InnoDB.sql konnte ich den Schuldigen nicht genau bestimmen. Jedenfalls schätze ich Ihre Hilfe.
Alfish
4

Ich habe vor einiger Zeit einen Drush-Befehl dafür geschrieben.

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

Hat vor ungefähr einem Jahr für mich gearbeitet und ist sich nicht sicher, ob sich die Drush-API seitdem geändert hat.

Sie können das in einer convert.drush.inc platzieren, zum Beispiel im Ordner .drush, oder es irgendwie auf Ihrer Site ausführen, zum Beispiel mit dem php-Block devel execute. Als Drush-Skript können Sie es so nennen:

drush convert-engine InnoDB

Warnung : Wenn jemand etwas mit der Datenbank macht, während diese Befehle ausgeführt werden, wird Ihre Datenbank komplett durcheinander gebracht. Nicht wiederherstellbar. Versetzen Sie Ihre Site in den Wartungsmodus und erstellen Sie ein Backup, bevor Sie dies versuchen! Und natürlich probieren Sie zuerst eine Entwicklungs- / Test-Site an :)

Berdir
quelle
5
Stimmen Sie Berdir zu und sichern Sie Ihre Site. Während dieser Operation wird Ihre Datenbank gesperrt. Wenn Sie ein Modul benötigen, das dies kann, probieren Sie DB Tuner aus .
Mikeytown2
@ Mikeytown2: Das ist ein ziemlich cooles Modul :)
Berdir
1
Nettes Skript, aber es scheint ziemlich übertrieben zu sein, als dies direkt unter dem MySQL-Client zu tun.
Tostinni
2
Das Skript besteht aus genau 5 Codezeilen. Der Rest ist, es mit Drush zu integrieren. Es gibt eine Möglichkeit, dies in einem einzelnen SQL-Befehl in MySQL zu tun. Eine oder andere Weise, Sie haben auf ein Skript zu schreiben.
Berdir