Howto: Reinigen Sie eine MySQL-InnoDB-Speicher-Engine?

132

Ist es möglich, eine MySQL-Innodb-Speicher-Engine zu bereinigen, damit keine Daten aus gelöschten Tabellen gespeichert werden?

Oder muss ich jedes Mal eine neue Datenbank neu erstellen?

Bryan Field
quelle
Was lässt Sie denken, dass MySQL Daten aus gelöschten Tabellen speichert?
Robert Munteanu
1
Wenn ich eine ganze Reihe großer Tabellen
Bryan Field,
2
@ RobertMunteanu: siehe bugs.mysql.com/bug.php?id=1341
Max

Antworten:

350

Hier ist eine vollständigere Antwort in Bezug auf InnoDB. Es ist ein langwieriger Prozess, aber die Mühe kann sich lohnen.

Beachten Sie, dass dies /var/lib/mysql/ibdata1die am stärksten ausgelastete Datei in der InnoDB-Infrastruktur ist. Es enthält normalerweise sechs Arten von Informationen:

  • Tabellendaten
  • Tabellenindizes
  • MVCC- Daten (Multiversioning Concurrency Control)
    • Rollback-Segmente
    • Leerzeichen rückgängig machen
  • Tabellenmetadaten (Datenwörterbuch)
  • Double Write Buffer (Hintergrundschreiben, um die Abhängigkeit vom Betriebssystem-Caching zu verhindern)
  • Puffer einfügen (Änderungen an nicht eindeutigen Sekundärindizes verwalten)
  • Siehe die Pictorial Representation of ibdata1

InnoDB-Architektur

InnoDB-Architektur

Viele Leute erstellen mehrere ibdataDateien in der Hoffnung auf eine bessere Verwaltung und Leistung des Speicherplatzes, aber diese Überzeugung ist falsch.

Kann ich OPTIMIZE TABLE?

Leider führt das Ausführen OPTIMIZE TABLEeiner InnoDB-Tabelle, die in der gemeinsam genutzten Tabellenbereichsdatei gespeichert ibdata1ist, zwei Dinge aus:

  • Macht die Daten und Indizes der Tabelle im Inneren zusammenhängend ibdata1
  • Fabrikate ibdata1wachsen , weil die zusammenhängenden Daten und Indexseiten angehängt anibdata1

Sie können jedoch Tabellendaten und Tabellenindizes von ibdata1diesen trennen und unabhängig voneinander verwalten.

Kann ich OPTIMIZE TABLEmit innodb_file_per_table?

Angenommen , Sie hinzufügen waren innodb_file_per_tablezu /etc/my.cnf (my.ini). Können Sie dann einfach OPTIMIZE TABLEauf allen InnoDB-Tabellen laufen ?

Gute Nachricht : Wenn Sie OPTIMIZE TABLEmit innodb_file_per_tableaktiviert ausführen , wird eine .ibdDatei für diese Tabelle erstellt. Wenn Sie beispielsweise eine Tabelle mit mydb.mytableeinem Datenverzeichnis von haben /var/lib/mysql, wird Folgendes erzeugt:

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

Das .ibdenthält die Datenseiten und Indexseiten für diese Tabelle. Toll.

Schlechte Nachrichten : Alles, was Sie getan haben, ist, die Datenseiten und Indexseiten von mydb.mytableaus dem Leben in zu extrahieren ibdata. Der Datenwörterbucheintrag für jede Tabelle, einschließlich mydb.mytable, verbleibt weiterhin im Datenwörterbuch (siehe Bilddarstellung von ibdata1 ). SIE KÖNNEN AN ibdata1DIESEM PUNKT NICHT EINFACH LÖSCHEN !!! Bitte beachten Sie, dass das ibdata1überhaupt nicht geschrumpft ist.

Bereinigung der InnoDB-Infrastruktur

Um ibdata1ein für alle Mal zu schrumpfen , müssen Sie Folgendes tun:

  1. Speichern Sie (z. B. mit mysqldump) alle Datenbanken in einer .sqlTextdatei ( SQLData.sqlwird unten verwendet).

  2. Löschen Sie alle Datenbanken (außer mysqlund information_schema). CAVEAT : Führen Sie dieses Skript vorsichtshalber aus, um sicherzustellen, dass alle Benutzerberechtigungen vorhanden sind:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
  3. Melden Sie sich bei MySQL an und führen Sie es aus SET GLOBAL innodb_fast_shutdown = 0;(Dadurch werden alle verbleibenden Transaktionsänderungen von ib_logfile0und vollständig gelöscht. ib_logfile1)

  4. Fahren Sie MySQL herunter

  5. Fügen Sie die folgenden Zeilen zu /etc/my.cnf(oder my.iniunter Windows) hinzu

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

    (Nebenbemerkung: Was auch immer Ihr Set ist innodb_buffer_pool_size, stellen Sie sicher, dass innodb_log_file_sizees 25% von ist innodb_buffer_pool_size.

    Auch: innodb_flush_method=O_DIRECTist unter Windows nicht verfügbar)

  6. Löschen ibdata*und ib_logfile*optional können Sie alle Ordner /var/lib/mysqlaußer entfernen /var/lib/mysql/mysql.

  7. Start MySQL (Dies wird neu ibdata1[10 MB standardmäßig] und ib_logfile0und ib_logfile1bei 1G jeweils).

  8. Importieren SQLData.sql

ibdata1Wird jetzt noch wachsen, enthält aber nur Tabellenmetadaten, da jede InnoDB-Tabelle außerhalb von existiert ibdata1. ibdata1enthält keine InnoDB-Daten und -Indizes für andere Tabellen mehr.

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

  • mytable.frm (Speicher-Engine-Header)
  • mytable.ibd (Tabellendaten und Indizes)

Mit der innodb_file_per_tableOption in /etc/my.cnfkönnen Sie ausführen OPTIMIZE TABLE mydb.mytableund die Datei /var/lib/mysql/mydb/mytable.ibdwird 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- ibdata1 Datei auf nur 500 MB verkleinert!

Versuche es. Wenn Sie weitere Fragen dazu haben, fragen Sie einfach. Vertrau mir; Dies wird sowohl kurzfristig als auch langfristig funktionieren.

VORBEHALT

Wenn in Schritt 6 MySQL aufgrund des Löschens des mysqlSchemas nicht neu gestartet werden kann , schauen Sie noch einmal in Schritt 2 nach. Sie haben die physische Kopie des mysqlSchemas erstellt. Sie können es wie folgt wiederherstellen:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

Gehen Sie zurück zu Schritt 6 und fahren Sie fort

UPDATE 2013-06-04 11:13 EDT

In Bezug auf das Setzen von innodb_log_file_size auf 25% von innodb_buffer_pool_size in Schritt 5 ist diese pauschale Regel eher alte Schule.

Zurück July 03, 2006hatte Percona einen schönen Artikel, warum man eine richtige innodb_log_file_size wählen sollte . Später Nov 21, 2008folgte Percona mit einem weiteren Artikel darüber, wie die richtige Größe basierend auf der Spitzenauslastung berechnet werden kann, wobei Änderungen im Wert von einer Stunde beibehalten werden .

Ich habe seitdem im DBA StackExchange Beiträge über die Berechnung der Protokollgröße geschrieben und wo ich auf diese beiden Percona-Artikel verwiesen habe.

Persönlich würde ich immer noch die 25% -Regel für eine Ersteinrichtung einhalten. Da die Arbeitslast im Laufe der Zeit in der Produktion genauer bestimmt werden kann, können Sie die Größe der Protokolle während eines Wartungszyklus in nur wenigen Minuten ändern .

RolandoMySQLDBA
quelle
9
Ich habe auch die Option innodb_file_per_table mit großer Wirkung verwendet. Mit 200 Datenbanken mit jeweils 200 Tabellen auf einem einzelnen Server konnte ich verschiedene Datenbanken mit verschiedenen Partitionen verknüpfen und daher mehr E / A-Puffer und Spindeln verwenden, die sonst verfügbar gewesen wären :)
Dave Rix
2
@ SeanDowney Übrigens denken Sie daran, innodb_open_tablesbei Bedarf zu erhöhen . Der Standardwert ist 300.
RolandoMySQLDBA
2
@ giorgio79 Sie müssen Ihren Bulk-Einsatz auf einen größeren Wert einstellen. Das ist ein guter Punkt. Ich werde die Essenz Ihrer Frage zu meiner Antwort hinzufügen.
RolandoMySQLDBA
3
In 32-Bit-Systemen ist ein 4-GB-Wert für innodb_buffer_pool_size nicht zulässig. MySQL startet stillschweigend mit deaktiviertem Innodb und die wiederhergestellten Tabellen werden in myisam geändert. Verwenden Sie einen etwas kleineren Wert, um das Problem zu beheben.
David
5
Guter Gott. Ich möchte nur sagen, dass dies vielleicht eine der besten Antworten ist, die ich je auf SO Verdammt gute Arbeit gesehen habe, Sir. Hat mir geholfen, eine Lösung für mein Problem zu finden, als ich beim Importieren einer 154-g-Datenbank einen FEHLER 2013 (HY000) erhielt. Danke für die hervorragende Antwort!
Josh Brown
4

Die InnoDB-Engine speichert keine gelöschten Daten. Beim Einfügen und Löschen von Zeilen bleibt nicht verwendeter Speicherplatz in den InnoDB-Speicherdateien reserviert. Mit der Zeit nimmt der Gesamtspeicherplatz nicht ab, aber mit der Zeit wird der gelöschte und freigegebene Speicherplatz vom DB-Server automatisch wiederverwendet.

Sie können den von der Engine verwendeten Speicherplatz durch eine manuelle Neuorganisation der Tabellen weiter optimieren und verwalten. Speichern Sie dazu die Daten in den betroffenen Tabellen mit mysqldump, löschen Sie die Tabellen, starten Sie den mysql-Dienst neu und erstellen Sie die Tabellen aus den Speicherauszugsdateien neu.

bigjeff
quelle