Ich habe dies bereits im Oktober 2010 in StackOverflow angesprochen .
Beachten Sie die am stärksten ausgelastete Datei in der InnoDB-Infrastruktur: / var / lib / mysql / ibdata1
Diese Datei enthält normalerweise vier Arten von Informationen
- Tabellendaten
- Tabellenindizes
- MVCC-Daten (Multiversioning Concurrency Control)
- Tabellenmetadaten (Liste der Tablespace-IDs)
Das Ausführen OPTIMIZE TABLE
gegen eine in ibdata1 gespeicherte InnoDB-Tabelle bewirkt zwei Dinge:
- Macht die Daten und Indizes der Tabelle innerhalb von ibdata1 zusammenhängend und ermöglicht so einen schnelleren Zugriff
- Dadurch wächst ibdata1, da die zusammenhängenden Daten und Indexseiten an ibdata1 angehängt werden
Sie können Tabellendaten und Tabellenindizes von ibdata1 trennen und sie unabhängig mit innodb_file_per_table verwalten , wird der große klaffende gesamte Speicherplatz in ibdata1 einfach nicht verschwinden und kann nicht zurückgefordert werden. Du musst mehr tun.
Um zu schrumpfen ibdata1 ein für alle Mal , müssen Sie Folgendes tun:
1) MySQLDump alle Datenbanken in eine SQL-Textdatei (nennen Sie es /root/SQLData.sql)
2) Löschen Sie alle Datenbanken (außer MySQL-Schema)
3) Fahren Sie mysql herunter
4) 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.
5) Löschen Sie ibdata1, ib_logfile0 und ib_logfile1
Zu diesem Zeitpunkt sollte nur das MySQL-Schema in / var / lib / mysql vorhanden sein
6) Starten Sie mysql neu
Dadurch wird ibdata1 mit 10 oder 18 MB (je nach MySQL-Version), ib_logfile0 und ib_logfile1 mit jeweils 1 GB neu erstellt
7) Laden Sie /root/SQLData.sql neu in mysql
ibdata1 wächst, enthält jedoch nur Tabellenmetadaten. In der Tat wird es im Laufe der Jahre sehr langsam wachsen. Der einzige Weg, wie ibdata1 schnell wachsen kann, ist, wenn Sie eine oder mehrere der folgenden Möglichkeiten haben:
- Viele DDL (
CREATE TABLE
, DROP TABLE
, ALTER TABLE
)
- Viele Transaktionen
- Viele Änderungen, die pro Transaktion festgeschrieben werden müssen
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 ausführen OPTIMIZE TABLE mydb.mytable;
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 !!!
UPDATE 19.04.2012 09:23 EDT
Wie können Sie ermitteln, welche Tabellen defragmentiert werden müssen, nachdem Sie die obigen Schritte ausgeführt haben? Es ist möglich, es herauszufinden, aber Sie werden es als Skript haben.
Hier ist ein Beispiel: Angenommen, Sie haben die Tabelle mydb.mytable
. Wenn innodb_file_per_table aktiviert ist, haben Sie die Datei /var/lib/mysql/mydb/mytable.ibd
Sie müssen zwei Nummern abrufen
FILESIZE FROM OS: So können Sie die Dateigröße vom Betriebssystem ermitteln
ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'
FILESIZE FROM INFORMATION_SCHEMA: Sie können die Dateigröße wie folgt aus information_schema.tables ermitteln:
SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';
Subtrahieren Sie einfach den INFORMATION_SCHEMA-Wert vom OS-Wert und dividieren Sie die Differenz durch den INFORMATION_SCHEMA-Wert.
Von dort aus würden Sie entscheiden, wie viel Prozent es für erforderlich halten, diese Tabelle zu defragmentieren. Natürlich defragmentieren Sie es mit einem der folgenden Befehle:
OPTIMIZE TABLE mydb.mytable;
oder
ALTER TABLE mydb.mytable ENGINE=InnoDB;