MySQL InnoDB gibt nach dem Löschen von Datenzeilen aus der Tabelle keinen Speicherplatz frei

140

Ich habe eine MySQL-Tabelle mit der InnoDB-Speicher-Engine. Es enthält ungefähr 2 Millionen Datenzeilen. Beim Löschen von Datenzeilen aus der Tabelle wurde kein zugewiesener Speicherplatz freigegeben. Auch die Größe der Datei ibdata1 wurde nach dem Ausführen des optimize tableBefehls nicht verringert .

Gibt es eine Möglichkeit, Speicherplatz von MySQL zurückzugewinnen?

Ich bin in einer schlechten Situation; Diese Anwendung wird an ungefähr 50 verschiedenen Orten ausgeführt, und jetzt tritt bei fast allen das Problem des geringen Speicherplatzes auf.

Sumit Deo
quelle
Nach dem Ausführen des Befehls "Optimieren" wurde die Größe der Datei "ibdata1" nicht verringert.
Sumit Deo
4
Ich denke, dass dieser Kommentar besser in Ihre Antwort bearbeitet und dann gelöscht werden sollte
Ben Millwood
Mögliches Duplikat von stackoverflow.com/q/11751792/82114 (aber dieses war zuerst hier)
FlipMcF
1
"Auch die Größe der Datei ibdata1 wurde nach dem Ausführen des Befehls" Tabelle optimieren "nicht verringert" , weil Sie deaktiviert sindinnodb_file_per_table . Die gute Nachricht ist, dass diese Option onin neueren Versionen von MySQL standardmäßig verfügbar ist.
Buchhalter
Ich führe "Tabelle xxxx optimieren" aus und erhalte die Meldung "Tabelle unterstützt keine Optimierung, stattdessen wird neu erstellt + analysiert." Nachdem ich "du -h / var / lib / mysql" auf einer Shell ausgeführt hatte, konnte ich sehen, dass die Datenbank geschrumpft war.
user1097111

Antworten:

137

MySQL reduziert die Größe von ibdata1 nicht. Je. Selbst wenn Sie den verwendeten optimize tableSpeicherplatz von gelöschten Datensätzen freigeben, wird er später wiederverwendet.

Eine Alternative besteht darin, den zu verwendenden Server zu konfigurieren. innodb_file_per_tableDies erfordert jedoch eine Sicherung, ein Löschen der Datenbank und eine Wiederherstellung. Die positive Seite ist, dass die .ibd-Datei für die Tabelle nach einem reduziert wird optimize table.

Leonel Martins
quelle
4
MySQL 5.5-Dokumente zum Status des InnoDB-Datei-pro-Tabelle-Modus "Um die Funktionen von [InnoDB-Datei-pro-Tabelle] für eine vorhandene Tabelle zu nutzen, können Sie die Einstellung Datei-pro-Tabelle aktivieren und ALTER TABLE t ENGINE=INNODBfür die vorhandene Tabelle ausführen . "" Dies bedeutet, dass Sie diese Funktion aktivieren, die vorhandenen Tabellen in eine separate InnoDB-Datei mit dem Befehl ALTER TABLE "konvertieren" und dann die Tabelle OPTIMIEREN können, um ihre Größe zu verringern. Sobald Sie fertig sind, müssen Sie jedoch herausfinden, wie Sie die (riesige) InnoDB-Quelldatei löschen können ...
Josh
9
Ich denke, dies beantwortet die Frage technisch, aber ich würde erwarten, dass die Mehrheit der Leute, die dieses Thema suchen, nach dem tatsächlichen Prozess sucht, um den Speicherplatz zu verkleinern / zurückzugewinnen, den diese Antwort nicht bietet.
Manachi
@Manachi Der Prozess ist "Konfigurieren des Servers für die Verwendung von innodb_file_per_table", "Sichern" des Servers, "Löschen der Datenbank (en)", Stoppen der MySQL, Löschen der .ibd, Starten des Servers und Wiederherstellen der Datenbank (en). Mit MySQL 5.5+ können Sie das verwenden, was Josh gesagt hat. Nachdem Sie alle Tabellen geändert haben, stoppen Sie den Server, löschen Sie die riesige .ibd und starten Sie sie erneut.
Leonel Martins
39

Hatte gerade das gleiche Problem.

Was passiert ist, dass innodb auch dann keinen Speicherplatz freigibt, wenn Sie die Datenbank löschen. Ich musste exportieren, MySQL stoppen, die Dateien manuell entfernen, MySQL starten, Datenbank und Benutzer erstellen und dann importieren. Gott sei Dank hatte ich nur Zeilen im Wert von 200 MB, aber 250 GB Innodb-Datei wurden geschont.

Fail by Design.

Gilm
quelle
10
Ja, das ist definitiv ein Fehlschlag.
Trusktr
1
MySql 5.5 hat das gleiche Problem: Ich habe "Tabelle optimieren" ausgeführt, um die Festplattennutzung einer 28-GB-Tabelle zu reduzieren. Die Operation hat wahrscheinlich versucht, einen optimierten Klon des ursprünglichen zu erstellen, und dabei den gesamten Speicherplatz auf der Partition belegt. Jetzt ist "Tabelle optimieren" fehlgeschlagen und ich habe keinen Platz auf der Partition, selbst nachdem ich die gesamte Datenbank gelöscht habe ... sehr enttäuschend.
Basilikode
1
Und 4+ Jahre später stieß ich auf das gleiche Problem mit MySQL. MS SQL ist ähnlich: dba.stackexchange.com/questions/47310/…
Csaba Toth
24

Wenn Sie innodb_file_per_table nicht verwenden , ist die Rückgewinnung von Speicherplatz möglich, aber recht langwierig und erfordert erhebliche Ausfallzeiten.

Das How To ist ziemlich ausführlich - aber ich habe den relevanten Teil unten eingefügt.

Stellen Sie sicher, dass Sie auch eine Kopie Ihres Schemas in Ihrem Speicherauszug aufbewahren.

Derzeit können Sie eine Datendatei nicht aus dem Systemtabellenbereich entfernen. Gehen Sie folgendermaßen vor, um die Größe des Systemtabellenbereichs zu verringern:

Verwenden Sie mysqldump, um alle Ihre InnoDB-Tabellen zu sichern.

Stoppen Sie den Server.

Entfernen Sie alle vorhandenen Tablespace-Dateien, einschließlich der Dateien ibdata und ib_log. Wenn Sie eine Sicherungskopie der Informationen aufbewahren möchten, kopieren Sie alle ib * -Dateien an einen anderen Speicherort, bevor Sie die Dateien in Ihrer MySQL-Installation entfernen.

Entfernen Sie alle .frm-Dateien für InnoDB-Tabellen.

Konfigurieren Sie einen neuen Tablespace.

Starten Sie den Server neu.

Importieren Sie die Dump-Dateien.

FlipMcF
quelle
Vielen Dank für die Schritte , einschließlich - AFAICT das ‚wie‘ Link diese Informationen nicht mehr enthält
Aland
3

Zehn Jahre später hatte ich das gleiche Problem. Ich habe es folgendermaßen gelöst:

  • Ich habe alle verbleibenden Datenbanken optimiert.
  • Ich habe meinen Computer und MySQL unter Diensten neu gestartet (Windows + r -> services.msc).

Das ist alles :)

Matheus Douglas
quelle
1

Eine andere Möglichkeit, das Problem der Speicherplatzrückgewinnung zu lösen, besteht darin, mehrere Partitionen in tabellenbasierten, wertbasierten Partitionen zu erstellen und die Partition einfach zu löschen / abzuschneiden, um den Speicherplatz zurückzugewinnen. Dadurch wird der Speicherplatz freigegeben, der von den gesamten in der jeweiligen Partition gespeicherten Daten verwendet wird.

Wenn Sie die Partitionierung für Ihre Tabelle einführen, sind einige Änderungen im Tabellenschema erforderlich, z. B. - Eindeutige Schlüssel, Indizes mit Partitionsspalte usw.

Anand Immannavar
quelle
0

Vor einem Jahr hatte ich auch das gleiche Problem mit der mysql5.7-Version und ibdata1 belegte 150 GB. Also habe ich Tablespaces rückgängig gemacht

Mysqldump-Backup erstellen MySQL-
Dienst
beenden Alle Daten aus dem Datenverzeichnis entfernen
Fügen Sie den folgenden Parameter zum Rückgängigmachen des Tabellenbereichs in der aktuellen Datei my.cnf hinzu

 #undo tablespace
  innodb_undo_directory =  /var/lib/mysql/
  innodb_rollback_segments = 128 
  innodb_undo_tablespaces = 3
  innodb_undo_logs = 128  
  innodb_max_undo_log_size=1G
  innodb_undo_log_truncate = ON

Starten Sie den MySQL-Dienst
die MySQL-Sicherung mysqldump

Problem gelöst !!

Gajendra
quelle
-1

Es gibt verschiedene Möglichkeiten, Speicherplatz zurückzugewinnen, nachdem Daten aus der Tabelle für die MySQL Inodb-Engine gelöscht wurden

Wenn Sie innodb_file_per_table nicht von Anfang an verwenden, können Sie nur alle Daten sichern, alle Dateien löschen, die Datenbank neu erstellen und die Daten erneut importieren (siehe Antworten von FlipMcF oben).

Wenn Sie innodb_file_per_table verwenden, können Sie es versuchen

  1. Wenn Sie alle Daten löschen können, werden mit dem Befehl "Daten abschneiden" Daten gelöscht und Speicherplatz für Sie zurückgefordert.
  2. Der Befehl "Tabelle ändern" löscht die Tabelle und erstellt sie neu, damit Speicherplatz wiederhergestellt werden kann. Führen Sie daher nach dem Löschen von Daten eine Änderungstabelle aus, die nichts ändert, um die Festplatte freizugeben (dh: Tabelle TBL_A hat den Zeichensatz uf8, nach dem Löschen der Daten ALTER TABLE TBL_A Zeichensatz utf8 -> Dieser Befehl ändert nichts an Ihrer Tabelle, aber MySQL erstellt Ihre Tabelle neu und gewinnt sie zurück Festplattenplatz
  3. Erstellen Sie TBL_B wie TBL_A. Fügen Sie ausgewählte Daten, die Sie von TBL_A behalten möchten, in TBL_B ein. Löschen Sie TBL_A und benennen Sie TBL_B in TBL_A um. Diese Methode ist sehr effektiv, wenn TBL_A und die zu löschenden Daten groß sind (der Befehl delete in MySQL innodb hat eine sehr schlechte Leistung).
Bùi Đức Khánh
quelle