So verkleinern / löschen Sie die ibdata1-Datei in MySQL

561

Ich verwende MySQL in localhost als "Abfragetool" zum Ausführen von Statistiken in R, dh jedes Mal, wenn ich ein R-Skript ausführe, erstelle ich eine neue Datenbank (A), erstelle eine neue Tabelle (B) und importiere die Daten in B. Senden Sie eine Abfrage, um das zu erhalten, was ich brauche, und lassen Sie dann B und A fallen.

Es funktioniert gut für mich, aber ich stelle fest, dass die Größe der ibdata-Datei schnell zunimmt. Ich habe nichts in MySQL gespeichert, aber die ibdata1-Datei hat bereits 100 MB überschritten.

Ich verwende mehr oder weniger die Standardeinstellung für MySQL für das Setup. Gibt es eine Möglichkeit, die ibdata1-Datei nach einem festgelegten Zeitraum automatisch zu verkleinern / löschen?

lokheart
quelle

Antworten:

777

Das ibdata1nicht schrumpfen ist eine besonders ärgerliche Funktion von MySQL. Die ibdata1Datei kann nur verkleinert werden, wenn Sie alle Datenbanken löschen, die Dateien entfernen und einen Speicherauszug neu laden.

Sie können MySQL jedoch so konfigurieren, dass jede Tabelle einschließlich ihrer Indizes als separate Datei gespeichert wird. Auf diese Weise ibdata1wird nicht so groß. Laut dem Kommentar von Bill Karwin ist dies ab Version 5.6.6 von MySQL standardmäßig aktiviert.

Es ist eine Weile her, dass ich das getan habe. Um Ihren Server so my.cnfeinzurichten, dass für jede Tabelle separate Dateien verwendet werden, müssen Sie Folgendes ändern , um Folgendes zu aktivieren:

[mysqld]
innodb_file_per_table=1

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

Wenn Sie den Speicherplatz zurückfordern möchten, müssen ibdata1Sie die Datei tatsächlich löschen:

  1. Führen Sie eine mysqldumpder Datenbanken, Prozeduren, Trigger usw. mit Ausnahme der Datenbanken mysqlund ausperformance_schema
  2. Löschen Sie alle Datenbanken mit Ausnahme der beiden oben genannten Datenbanken
  3. Stoppen Sie MySQL
  4. Löschen ibdata1und ib_logDateien
  5. Starten Sie MySQL
  6. Vom Speicherauszug wiederherstellen

Wenn Sie MySQL in Schritt 5 starten, werden die ibdata1und ib_log-Dateien neu erstellt.

Jetzt können Sie loslegen. Wenn Sie eine neue Datenbank für die Analyse erstellen, befinden sich die Tabellen in separaten ibd*Dateien, nicht in ibdata1. Da Sie die Datenbank normalerweise bald danach ibd*löschen , werden die Dateien gelöscht.

http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

Sie haben dies wahrscheinlich gesehen:
http://bugs.mysql.com/bug.php?id=1341

Mit dem Befehl ALTER TABLE <tablename> ENGINE=innodboder OPTIMIZE TABLE <tablename>kann man Daten und Indexseiten aus ibdata1 extrahieren, um Dateien zu trennen. Ibdata1 wird jedoch nur verkleinert, wenn Sie die obigen Schritte ausführen.

In Bezug auf die information_schemaist das weder notwendig noch möglich zu fallen. Es ist in der Tat nur eine Reihe von schreibgeschützten Ansichten, keine Tabellen. Und ihnen sind keine Dateien zugeordnet, nicht einmal ein Datenbankverzeichnis. Das informations_schemaverwendet die Speicher-DB-Engine und wird beim Stoppen / Neustarten von mysqld gelöscht und neu generiert. Siehe https://dev.mysql.com/doc/refman/5.7/en/information-schema.html .

John P.
quelle
16
@JordanMagnuson Mach dir nicht die Mühe, information_schema fallen zu lassen. Es ist in der Tat nur eine Reihe von schreibgeschützten Ansichten, keine Tabellen. Und ihnen sind keine Dateien zugeordnet. Es gibt nicht einmal ein Verzeichnis für die Datenbank. Das informations_schema verwendet die Speicher-DB-Engine und wird beim Stoppen / Neustarten von mysqld gelöscht und neu generiert. Siehe dev.mysql.com/doc/refman/5.5/en/information-schema.html . In Bezug auf das Leistungsschema habe ich dieses Schema selbst nicht verwendet.
John P
4
Ich weiß nicht, ob dies eine aktuelle Sache ist, aber sobald die Option innodb_file_per_table aktiviert ist, können Sie einfach "ALTER TABLE <Tabellenname> ENGINE = InnoDB" ausführen (auch wenn es bereits InnoDB ist) und die Tabelle in ihre individuelle Datei verschieben . Keine Notwendigkeit, Datenbanken und dergleichen zu löschen.
CR.
3
+1 FWIW, MySQL 5.6 ist innodb_file_per_tablestandardmäßig aktiviert.
Bill Karwin
3
Ja, es wird erwartet, dass ibdata1 zusammen mit den anderen Dateien vorhanden ist. Die Datei ibdata1 enthält weiterhin Metadaten zu Tabellen, dem Rückgängig-Protokoll und Puffern.
John P
1
Ich habe aufgrund der Datei ibdata1 nicht mehr genügend Speicherplatz auf meinem Server, sodass ich die Datenbanken nicht einmal sichern kann. Wäre es dasselbe, wenn Sie nur die Dateien in / var / lib / mysql verschieben (außer "mysql", "ibdata1", "ib_logfile0" und "ib_logfile1") und dann den Schritten folgen? Siehe stackoverflow.com/questions/2482491/…
Sophivorus
47

Hinzufügen zu John Ps Antwort ,

Für ein Linux-System können die Schritte 1 bis 6 mit den folgenden Befehlen ausgeführt werden:

  1. mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
  2. DROP DATABASE [database_name];
  3. sudo /etc/init.d/mysqld stop
  4. sudo rm /var/lib/mysql/ibdata1
    sudo rm /var/lib/mysql/ib_logfile (und löschen Sie alle anderen ib_log-Dateien, die benannt werden können ib_logfile0, ib_logfile1etc ...)
  5. sudo /etc/init.d/mysqld start
  6. create database [database_name];
  7. mysql -u [username]-p[root_password] [database_name] < dumpfilename.sql

Warnung: Diese Anweisungen führen dazu, dass Sie andere Datenbanken verlieren, wenn Sie andere Datenbanken auf dieser MySQL-Instanz haben. Stellen Sie sicher, dass die Schritte 1, 2 und 6, 7 geändert wurden, um alle Datenbanken abzudecken, die Sie behalten möchten.

Vinay Vemula
quelle
6
Sie müssen 1,2 und 6 für jede Datenbank mit InnoDB-Tabellen wiederholen.
Marquis von Lorne
4
Sie benötigen noch ein paar Schritte zwischen # 5 und # 6. Sie müssen die Datenbank neu erstellen und die Berechtigungen neu zuweisen. Also von der MySQL-Client-Eingabeaufforderung create database database_name;und danngrant all privileges on database_name.* to 'username'@'localhost' identified by 'password';
Fred
1
@fred Ich musste dabei keine Privilegien gewähren. Möglicherweise, weil ich die Datenbank mit demselben Namen neu erstellt habe?
Crmpicco
2
Um das Passwort an einer Password:Eingabeaufforderung einzugeben (was sicherer ist), geben Sie einfach -pein Passwort ein.
ADTC
Trigger, Ereignisse und Routinen / Funktionen werden nur ausgegeben, wenn Sie mysqldump dazu auffordern. Fügen Sie auch die --triggers, --events und --routines hinzu, wenn eine Ihrer Datenbanken sie enthält. Dumpen Sie einfach mit --all-database, um alle Datenbanken auf einmal anstatt einzeln zu sichern.
Friek
34

Wenn Sie innodb-Tabellen löschen, gibt MySQL den Speicherplatz in der ibdata-Datei nicht frei. Deshalb wächst es weiter. Diese Dateien schrumpfen kaum.

So verkleinern Sie eine vorhandene ibdata-Datei:

http://dev.mysql.com/doc/refman/5.5/en/innodb-resize-system-tablespace.html

Sie können dies skripten und planen, dass das Skript nach einem festgelegten Zeitraum ausgeführt wird. Für das oben beschriebene Setup scheinen jedoch mehrere Tablespaces eine einfachere Lösung zu sein.

Wenn Sie die Konfigurationsoption verwenden innodb_file_per_table, erstellen Sie mehrere Tablespaces. Das heißt, MySQL erstellt für jede Tabelle separate Dateien anstelle einer gemeinsam genutzten Datei. Diese separaten Dateien werden im Verzeichnis der Datenbank gespeichert und beim Löschen dieser Datenbank gelöscht. Dies sollte die Notwendigkeit beseitigen, ibdata-Dateien in Ihrem Fall zu verkleinern / löschen.

Weitere Informationen zu mehreren Tablespaces:

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

Titanoboa
quelle
erster Link gebrochen, engste Übereinstimmung, die ich finden konnte: dev.mysql.com/doc/refman/5.5/en/…
BlackICE
14

Wenn Sie die InnoDB-Speicher-Engine für (einige) Ihrer MySQL-Tabellen verwenden, sind Sie wahrscheinlich bereits auf ein Problem mit der Standardkonfiguration gestoßen. Wie Sie vielleicht im Datenverzeichnis Ihres MySQL (in Debian / Ubuntu - / var / lib / mysql) bemerkt haben, liegt eine Datei namens 'ibdata1'. Es enthält fast alle InnoDB-Daten (es ist kein Transaktionsprotokoll) der MySQL-Instanz und kann sehr groß werden. Standardmäßig hat diese Datei eine anfängliche Größe von 10 MB und wird automatisch erweitert. Leider können InnoDB-Datendateien von Natur aus nicht verkleinert werden. Aus diesem Grund wird durch DELETEs, TRUNCATEs, DROPs usw. der von der Datei verwendete Speicherplatz nicht zurückgefordert.

Ich denke, Sie können dort eine gute Erklärung und Lösung finden:

http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/

Vik
quelle
11

Schreiben Sie die Prozedur der akzeptierten Antwort schnell in Bash:

#!/usr/bin/env bash
DATABASES="$(mysql -e 'show databases \G' | grep "^Database" | grep -v '^Database: mysql$\|^Database: binlog$\|^Database: performance_schema\|^Database: information_schema' | sed 's/^Database: //g')"
mysqldump --databases $DATABASES -r alldatabases.sql && echo "$DATABASES" | while read -r DB; do
    mysql -e "drop database \`$DB\`"
done && \
    /etc/init.d/mysql stop && \
    find /var/lib/mysql -maxdepth 1 -type f \( -name 'ibdata1' -or -name 'ib_logfile*' \) -delete && \
    /etc/init.d/mysql start && \
    mysql < alldatabases.sql && \
    rm -f alldatabases.sql

Speichern unter purge_binlogs.shund ausführen als root.

Ausgeschlossen mysql, information_schema, performance_schema(und binlogVerzeichnis).

Angenommen, Sie haben Administrator-Anmeldeinformationen /root/.my.cnfund Ihre Datenbank befindet sich im Standardverzeichnis /var/lib/mysql.

Sie können Binärprotokolle auch nach dem Ausführen dieses Skripts löschen, um mehr Speicherplatz wiederzugewinnen.

PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;
Pierre-Alexis de Solminihac
quelle
Ich bin mir immer noch nicht sicher warum, aber heute wurden einige meiner InnoDB-Tabellen während eines ähnlichen Prozesses beschädigt, sodass ich sie nicht entfernen würde, alldatabases.sqlbevor ich noch einmal überprüft habe, ob alle Tabellen fehlerfrei sind. Einige Verbesserungen: innodb_fast_shutdown=0Vor dem Herunterfahren festlegen, autocommit=0vor dem Importieren der SQL-Datei COMMITfestlegen , ausführen und autocommit=1nach dem Importieren der SQL-Datei festlegen , mysqlcheck --all-databasesvor dem Löschen der Sicherung verwenden.
Victor
6

Wenn Ihr Ziel darin besteht, den freien Speicherplatz von MySQL zu überwachen und Sie MySQL nicht stoppen können, um Ihre ibdata-Datei zu verkleinern, rufen Sie sie über Tabellenstatusbefehle ab. Beispiel:

MySQL> 5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'

MySQL <5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'

Vergleichen Sie diesen Wert dann mit Ihrer ibdata-Datei:

du -b ibdata1

Quelle: http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html

Cyno
quelle
4

In einer neuen Version der oben genannten MySQL-Server-Rezepte wird die "MySQL" -Datenbank zerstört. In der alten Version funktioniert es. In neuen Tabellen wechseln einige Tabellen zum Tabellentyp INNODB, wodurch Sie sie beschädigen. Der einfachste Weg ist:

  • Dump alle Ihre Datenbanken
  • deinstalliere mysql-server,
  • add in blieb my.cnf:
    [mysqld]
    innodb_file_per_table=1
  • Löschen Sie alles in / var / lib / mysql
  • installiere mysql-server
  • Benutzer und Datenbanken wiederherstellen
Rollgabelschlüssel
quelle
1

Wie bereits erwähnt, können Sie ibdata1 nicht verkleinern (dazu müssen Sie sichern und neu erstellen), aber es besteht auch oft keine wirkliche Notwendigkeit.

Bei Verwendung von Autoextend (wahrscheinlich die häufigste Größeneinstellung) weist ibdata1 den Speicher vorab zu und wächst jedes Mal, wenn er fast voll ist. Dies beschleunigt das Schreiben, da bereits Speicherplatz zugewiesen ist.

Wenn Sie Daten löschen, werden diese nicht verkleinert, aber der Speicherplatz in der Datei wird als nicht verwendet markiert. Wenn Sie jetzt neue Daten einfügen, wird der leere Speicherplatz in der Datei wiederverwendet, bevor die Datei weiter vergrößert wird.

Es wird also nur dann weiter wachsen, wenn Sie diese Daten tatsächlich benötigen. Wenn Sie den Speicherplatz nicht tatsächlich für eine andere Anwendung benötigen, gibt es wahrscheinlich keinen Grund, ihn zu verkleinern.

Steveayre
quelle
66
Ich denke, Sie sind etwas zu abweisend gegenüber der Notwendigkeit, den Speicherplatz freizugeben.
Zeichnen
2
Ich habe eine 60Gig Solid State Partition. Ich habe schnell keinen Platz mehr, da ich mit 4 + Gig-Datenbanken arbeite. Ich
möchte MySQL
3
Vielen Dank für diese Antwort, es ist sehr hilfreich. Ich habe einige Tabellen aus Legacy-Daten gelöscht. Es ist gut zu wissen, dass die Größe auf der Festplatte nicht so schnell wieder zunimmt.
Brad
1
Ich habe eine 500G ibdata1-Datei - aber fast alle darin gespeicherten Daten werden jetzt in datenbankinternen Dateien gespeichert. Ich muss diese kollossale Platzverschwendung unbedingt verkleinern!
Frankster
2
Kompletter Unsinn! Eine Datei, die immer weiter aufbläht, muss gekürzt werden, unabhängig davon, ob Ihnen der Speicherplatz ausgeht oder nicht . Ich würde es a nennen storage leak.
ADTC