MySql - Ändern von innodb_file_per_table für eine Live-Datenbank

18

Ich habe eine große MySQL-Datenbank (150 GB) und erst jetzt ist mir aufgefallen, dass die auf festgelegt innodb_file_per_tableist, offwodurch die gesamte Datenbank in einer einzigen Datei gehostet wird ( ibdata1). Ich möchte die Datenbank innodb_file_per_tablenachträglich aktivieren und in mehrere Dateien aufteilen. Wie geht das am besten?

Ran
quelle

Antworten:

32

Es gibt wirklich nur einen Weg, dies durchzuziehen. Sie müssen die Daten mit mysqldumps exportieren, alle Datenbanken löschen, mysqld herunterfahren, ib_logfile0 löschen, ib_logfile1 löschen, ibdata1 löschen, innodb_file_per_tableunter der [mysqld]Überschrift hinzufügen, mysql starten.

Ich habe diese Antwort im Oktober 2010 in StackOverflow gepostet

Hier sind die Schritte vertikal aufgelistet:

Schritt 01) MySQLDump alle Datenbanken in eine SQL-Textdatei (nennen Sie es SQLData.sql)

Schritt 02) Alle Datenbanken löschen (außer MySQL-Schema)

Schritt 03) Fahren Sie mysql herunter

CAVEAT : Um nicht festgeschriebene Transaktionen vollständig aus den InnoDB-Dateien zu entfernen , führen Sie diese aus

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

Schritt 04) Fügen Sie die folgenden Zeilen zu /etc/my.cnf hinzu

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

Anmerkung: Unabhängig von Ihrer Einstellung für innodb_buffer_pool_size müssen Sie sicherstellen, dass innodb_log_file_size 25% von innodb_buffer_pool_size beträgt.

Schritt 05) Löschen Sie ibdata1, ib_logfile0 und ib_logfile1

Zu diesem Zeitpunkt sollte nur das MySQL-Schema in / var / lib / mysql vorhanden sein

Schritt 06) Starten Sie mysql neu

Dadurch wird ibdata1 bei 10 MB, ib_logfile0 und ib_logfile1 bei jeweils 1 GB neu erstellt

Schritt 07) Laden Sie SQLData.sql erneut in mysql

ibdata1 wächst, enthält jedoch nur Tabellenmetadaten

Jede InnoDB-Tabelle existiert außerhalb von ibdata1

Angenommen, Sie haben eine InnoDB-Tabelle mit dem Namen mydb.mytable. Wenn Sie in / var / lib / mysql / mydb gehen, sehen Sie zwei Dateien, die die Tabelle darstellen

  • mytable.frm (Speicher-Engine-Header)
  • mytable.ibd (Heimat von Tabellendaten und Tabellenindizes für mydb.mytable)

ibdata1 enthält nie mehr InnoDB-Daten und -Indizes.

Mit der Option innodb_file_per_table in /etc/my.cnf können Sie OPTIMIZE TABLE mydb.mytable ausführen, und die Datei /var/lib/mysql/mydb/mytable.ibd wird tatsächlich verkleinert.

Ich habe dies in meiner Karriere als MySQL-DBA viele Male getan

Tatsächlich habe ich beim ersten Mal eine 50 GB große ibdata1-Datei auf 500 MB reduziert.

Versuche es. Wenn Sie weitere Fragen dazu haben, senden Sie mir eine E-Mail. Vertrau mir. Dies wird kurzfristig und langfristig funktionieren. !!!

Es gibt eine Alternative, die die InnoDB-Tabelle extrahiert, ohne ibdata1 zu verkleinern.

Schritt 01) Fügen Sie die folgenden Zeilen zu /etc/my.cnf hinzu

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

Schritt 02) service mysql restart

Schritt 03) So extrahieren Sie eine einzelne InnoDB-Tabelle mit dem Namen mydb.mytable:

ALTER TABLE mydb.mytable ENGINE=InnoDB;

Dadurch wird eine Datei erstellt, wobei die ursprüngliche Strukturdatei beibehalten wird

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

Sie können dies für jede InnoDB-Tabelle tun. Leider bleibt ibdata1 bei 150GB.

RolandoMySQLDBA
quelle
Beim Ausführen des Neuladens aus den .sql-Dateien erhalte ich den folgenden Fehler. Irgendwelche ERROR 1071 (42000) at line 25: Specified key was too long; max key length is 1000 bytesIdeen?
Ran
@Ran bitte als separate Frage posten.
RolandoMySQLDBA
na klar
Ran
Wenn Sie die Option für jede einzelne Tabelle festlegen innodb_file_per_tableund dann ALTER TABLEausführen, können Sie die Datei ibdata1 löschen, um den Speicherplatz zurückzugewinnen, ohne ihn wiederherstellen zu müssen?
SystemParadox
1
@SystemParadox ABSOLUT NICHT !!!!!!!! Sie verlieren das Datenwörterbuch.
RolandoMySQLDBA
5

Wenn Sie den Speicherplatz von ibdata zurückfordern möchten, ist ein Dump / Restore Ihre einzige Wahl, wie Rolando betont . Es ist wahrscheinlich auch am besten für die Leistung, dies zu tun.

Wenn Sie jedoch nur Ihre Verluste reduzieren und diese 150 GB auf der Festplatte verlieren möchten, können Sie einfach innodb_file_per_tablemy.cnf aktivieren und Ihren Server neu starten.

Dann geben Sie für jede Tabelle Folgendes ein:

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

Das Problem hierbei ist, dass große Tablespaces eine Weile dauern.

Ich würde vorschlagen, einen Slave Ihrer Live-Datenbank einzurichten, die Konvertierung auf dem Slave auszuführen, dann entweder den Master / Slave auszuschalten und den neuen Datenbereich auf den Master zu kopieren oder den Slave zum Master zu befördern, sobald er aufgeholt hat .

Sie werden Schwierigkeiten haben, diese Änderung ohne Ausfallzeiten durchzuführen.

Derek Downey
quelle
+1 dafür, dass du brutal ehrlich bist und sagst: "Reduziere deine Verluste." Sie hätten auch sagen können, beißen Sie die Kugel.
RolandoMySQLDBA
Sie können pt-online-schema-change verwenden, um Ausfallzeiten beim Ausführen der Änderungstabelle zu vermeiden.
Cornernote