it-swarm.com.de

Wie kann ich einen mysqldump einer großen Datenbank optimieren?

Ich habe eine Symfony-Anwendung mit einer InnoDB-Datenbank von ~ 2 GB mit 57 Tabellen. Der Großteil der Datenbankgröße befindet sich in einer einzelnen Tabelle (~ 1,2 GB). Ich verwende derzeit mysqldump, um die Datenbank jede Nacht zu sichern.

Aufgrund meiner Comcast-Verbindung tritt häufig eine Zeitüberschreitung auf, wenn ich einen Dump manuell ausführe, bevor der Dump abgeschlossen ist, sodass ich den Dump erneut ausführen muss. [Ich führe derzeit einen Cron aus, der den Dump jeden Abend ausführt. Dies ist nur für Dumps, die ich manuell ausführe.]

Gibt es eine Möglichkeit, die Speicherauszüge für das Problem mit dem Verbindungszeitlimit zu beschleunigen, aber auch die Zeit zu begrenzen, in der der Server mit diesem Prozess beschäftigt ist?

Übrigens arbeite ich derzeit daran, die Größe der gesamten Datenbank zu reduzieren, um dieses Problem zu beheben.

179
Patrick

Der größte Engpass im Dump wie diesem ist die Laufwerks-E/A. Sie lesen eine Menge Daten und schreiben sie erneut. Sie können dies auf verschiedene Arten beschleunigen:

  • Stellen Sie sicher, dass Ihre Ausgabe auf ein anderes Laufwerk geht als auf das Laufwerk, auf dem die Datenbankdateien gespeichert sind. Dies macht einen großen Unterschied bei sich drehenden Festplatten, da die Laufwerksköpfe nicht ständig zwischen den Speicherorten wechseln, von denen gelesen wird und der Ort, an den geschrieben wird.
  • Die Ausgabe von mysqldump ist sehr komprimierbar. Wenn Sie also die Ausgabe nicht wie oben erwähnt von der Eingabe trennen können, leiten Sie die Ausgabe über gzip oder ähnliches weiter. Dies reduziert den Schreibaufwand (reduzieren Sie also die Gesamtlast IO und die Kopfbewegung) auf Kosten einer gewissen CPU-Zeit (für die Sie möglicherweise viel Zeit zur Verfügung haben) diese Zeiten sowieso).
  • Außerdem (ebenfalls oder anstelle der Komprimierung) wird die Ausgabe über ein Pipe-Dienstprogramm (wie pv ) geleitet, das große Schreibpuffer unterstützt, um Blöcke, die auf die Laufwerke geschrieben wurden, stärker zu gruppieren, um wiederum den Effekt von head zu verringern - Bewegungslatenz - Dies macht einen großen Unterschied, wenn Sie die Option --quick verwenden, um die Auswirkungen der Sicherung großer Tabellen auf RAM) zu verringern.
  • Führen Sie Ihren Sicherungsprozess nur aus, wenn IO load ansonsten niedrig ist.

Möglicherweise beheben Sie jedoch das falsche Problem: Es ist möglicherweise einfacher, die Verbindungsabbrüche zu beheben (obwohl die Reduzierung der durch Ihre Sicherungen verursachten E/A-Belastung dazu beiträgt, die Auswirkungen auf andere Benutzer zu verringern, lohnt es sich trotzdem, dies zu versuchen). Könnten Sie Ihre manuellen Sicherungen über Bildschirm (oder ähnliche Tools wie tmux ) ausführen? Auf diese Weise können Sie, wenn Ihre Verbindung zum Server unterbrochen wird, die Verbindung einfach wiederherstellen und erneut mit der Sitzung screen verbinden, ohne dass Prozesse unterbrochen werden.

Wenn Sie die Daten direkt über die Verbindung senden (dh Sie führen mysqldump auf Ihrem lokalen Computer für eine entfernte Datenbank aus, sodass der Speicherauszug lokal angezeigt wird), sollten Sie den Speicherauszug möglicherweise zuerst auf dem Server ausführen, nach Bedarf komprimieren und dann übertragen die Daten über das Netzwerk mit einem Tool (z. B. rsync), das Teilübertragungen unterstützt, sodass Sie die Übertragung fortsetzen können (anstatt sie neu zu starten), wenn ein Verbindungsabbruch sie unterbricht.

Als Teil Ihrer "Reduzierung der Größe der Gesamtdatenbank zur Behebung dieses Problems" würde ich vermuten, dass sich ein großer Teil Ihrer Daten nicht ändert. Möglicherweise können Sie einen großen Teil der 1,2 GB von dieser Haupttabelle in eine andere verschieben und diesen von denjenigen entfernen, die vom Aufruf mysqldump kopiert wurden. Sie müssen diese Daten nicht jedes Mal sichern, wenn sie sich nie ändern. Das Aufteilen von Daten zwischen Tabellen und Datenbanken auf diese Weise wird normalerweise als Datenpartitionierung bezeichnet und ermöglicht es Ihnen auch, die Daten- und E/A-Last auf mehrere Laufwerke zu verteilen. High-End-Datenbanken unterstützen die automatische Partitionierung. In MySQL müssen Sie dies jedoch wahrscheinlich manuell tun und Ihre Datenzugriffsschicht ändern, um dies zu berücksichtigen.

Abweichend vom Thema für diese Site (daher sollten Sie sich wahrscheinlich an ServerFault oder SuperUser wenden, um zu fragen, ob Sie weitere Details benötigen): Wenn Sie aufgrund von Inaktivität scheinbar Verbindungen verlieren, überprüfen Sie die Optionen auf Ihrem SSH-Server und SSH-Client Stellen Sie sicher, dass Keep-Alive-Pakete aktiviert sind und häufig genug gesendet werden. Wenn Sie sehen, dass die Verbindung unterbrochen wird, auch wenn die Verbindung aktiv ist, können Sie auch versuchen, OpenVPN oder ähnliches zum Umbrechen der Verbindung zu verwenden. Es sollte ein kurzes Löschen behandelt werden, sogar ein vollständiges Löschen, wenn Ihre gesamte Verbindung einige Sekunden lang unterbrochen ist, z Server nicht bemerken.

139
David Spillett

EINBLICK IN BACKUPS MIT mysqldump

IMHO Backups zu machen ist eher eine Kunstform geworden, wenn man genau weiß, wie man es angeht

Sie haben Optionen

Option 1: mysqldump eine ganze mysql-Instanz

Dies ist die einfachste, das Kinderspiel !!!

mysqldump -h... -u... -p... --hex-blob --routines --triggers --all-databases | gzip > MySQLData.sql.gz

Alles in einer Datei geschrieben: Tabellenstrukturen, Indizes, Trigger, gespeicherte Prozeduren, Benutzer, verschlüsselte Passwörter. Andere mysqldump-Optionen können auch verschiedene Arten von INSERT-Befehlen, Protokolldateien und Positionskoordinaten aus Binärprotokollen, Datenbankerstellungsoptionen, Teildaten (Option --where) usw. exportieren.

Option 2: mysqldump separate Datenbanken in separate Datendateien

Beginnen Sie mit der Erstellung einer Liste von Datenbanken (2 Techniken, um dies zu tun)

Technik 1

mysql -h... -u... -p... -A --skip-column-names -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

Technik 2

mysql -h... -u... -p... -A --skip-column-names -e"SELECT DISTINCT table_schema FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

Technik 1 ist der schnellste Weg. Technik 2 ist die sicherste und sicherste. Technik 2 ist besser, da Benutzer manchmal Ordner für allgemeine Zwecke in/var/lib/mysql (Datenverzeichnis) erstellen, die nicht datenbankbezogen sind. Das Informationsschema würde den Ordner als Datenbank in der Tabelle information_schema.schemata registrieren. Technik 2 würde Ordner umgehen, die keine MySQL-Daten enthalten.

Sobald Sie die Liste der Datenbanken zusammengestellt haben, können Sie die Liste durchlaufen und sie mysqldumpen, auch parallel, wenn dies gewünscht wird.

for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
done
wait

Wenn zu viele Datenbanken gleichzeitig gestartet werden können, sichern Sie sie jeweils 10 Mal parallel:

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

Option 3: mysqldump separate Tabellen in separate Datendateien

Erstellen Sie zunächst eine Liste mit Tabellen

mysql -h... -u... -p... -A --skip-column-names -e"SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfTables.txt

Speichern Sie dann alle Tabellen in 10er-Gruppen

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DBTB in `cat ListOfTables.txt`
do
    DB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $2}'`
    mysqldump -h... -u... -p... --hex-blob --triggers ${DB} ${TB} | gzip > ${DB}_${TB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

Option 4: BENUTZEN SIE IHRE IMAGINATION

Probieren Sie Variationen der oben genannten Optionen sowie Techniken für saubere Schnappschüsse aus

Beispiele

  1. Ordnen Sie die Liste der Tabellen nach der Größe der aufsteigenden oder absteigenden Tabellen.
  2. Führen Sie "FLUSH TABLES WITH READ LOCK; SELECT SLEEP (86400)" mit einem separaten Prozess aus, bevor Sie mysqldumps starten. Beenden Sie diesen Vorgang, nachdem mysqldumps abgeschlossen sind. Dies ist hilfreich, wenn eine Datenbank sowohl InnoDB als auch MyISAM enthält
  3. Speichern Sie die mysqldumps in datierten Ordnern und drehen Sie alte Sicherungsordner heraus.
  4. Laden Sie die gesamte Instanz mysqldumps auf eigenständige Server.

[~ # ~] Einschränkung [~ # ~]

Nur Option 1 bringt alles. Der Nachteil ist, dass auf diese Weise erstellte mysqldumps nur in dieselbe Majot-Release-Version von mysql neu geladen werden können, mit der der mysqldump generiert wurde. Mit anderen Worten, ein mysqldump aus einer MySQL 5.0-Datenbank kann nicht in 5.1 oder 5.5 geladen werden. Der Grund ? Das MySQL-Schema unterscheidet sich grundlegend zwischen den Hauptversionen.

In den Optionen 2 und 3 werden Benutzernamen und Kennwörter nicht gespeichert.

Hier ist die allgemeine Methode zum Speichern der SQL-Zuschüsse für Benutzer, die lesbar und portabler ist

mysql -h... -u... -p... --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',Host,''';') FROM mysql.user WHERE user<>''" | mysql -h... -u... -p... --skip-column-names -A | sed 's/$/;/g' > MySQLGrants.sql

Option 3 speichert die gespeicherten Prozeduren nicht, sodass Sie Folgendes tun können

mysqldump -h... -u... -p... --no-data --no-create-info --routines > MySQLStoredProcedures.sql &

Ein weiterer Punkt, der beachtet werden sollte, betrifft InnoDB. Wenn Sie über einen großen InnoDB-Pufferpool verfügen, ist es sinnvoll, diesen so gut wie möglich zu leeren, bevor Sie Sicherungen durchführen. Andernfalls verbringt MySQL die Zeit damit, Tabellen mit übrig gebliebenen schmutzigen Seiten aus dem Pufferpool zu leeren. Folgendes schlage ich vor:

Führen Sie diesen SQL-Befehl ca. 1 Stunde vor dem Ausführen der Sicherung aus

SET GLOBAL innodb_max_dirty_pages_pct = 0;

In MySQL 5.5 ist standardmäßig innodb_max_dirty_pages_pct 75. In MySQL 5.1 und zurück ist standardmäßig innodb_max_dirty_pages_pct 90. Wenn Sie innodb_max_dirty_pages_pct auf 0 setzen, wird das Löschen schmutziger Seiten auf die Festplatte beschleunigt. Dies verhindert oder verringert zumindest die Auswirkungen der Bereinigung unvollständiger zweiphasiger Festschreibungen von InnoDB-Daten, bevor ein mysqldump für InnoDB-Tabellen ausgeführt wird.

FINAL Word ON mysqldump

Die meisten Leute scheuen mysqldump zugunsten anderer Tools und diese Tools sind in der Tat gut.

Solche Werkzeuge umfassen

  1. MAATKIT (parallele Dump / Wiederherstellen Skripte von Percona [Veraltet, aber großartig])
  2. XtraBackup (TopNotch Snapshot Backup von Percona)
  3. CDP R1Soft ( MySQL Module Option , die Momentaufnahmen macht)
  4. MySQL Enterprise Backup (früher InnoDB Hot Backups [kommerziell])

Wenn Sie den Geist eines echten MySQL-DBA haben, können Sie mysqldump annehmen und die vollständige Meisterschaft darüber erlangen, die erreicht werden kann. Mögen alle Ihre Backups Ihre Fähigkeiten als MySQL-DBA widerspiegeln .

122
RolandoMySQLDBA

Schauen Sie sich MySQL Replication Master to Slave an. Sie können die Datenbank des Masters auf einen anderen Datenbankserver mit derselben Datenbank klonen. Dies schließt die Master- und Slave-Identitäten ein. Slave erstellt selbst die exakte Kopie des Master-Datenbankservers und/oder seiner Datenbanken. Es kann eine Eins-Eins, Eins-Viele, Viele-Eins-Beziehung zwischen Master (s) und Slave (s) geben.

Der Slave liest kontinuierlich das Binärprotokoll am Master (das Bin-Protokoll speichert die auf dem Master-Datenbankserver geschriebenen Abfragen) und erhält Eingaben an seinen Slave-Datenbankserver. (Dies bedeutet, dass Ihre Master-Datenbank überhaupt nicht betroffen ist.)

Die gute Nachricht ist, dass Ihr MySQL-Server nicht zu stark beeinträchtigt wird, da Sie keine Ausfallzeiten oder langsamen Abfrageantworten bemerken. Wir verwenden es für 10-Gbit-Datenbanken und es funktioniert wie ein Zauber ohne Ausfallzeiten.

MySQL-Replikation auf demselben Computer

20
poelinca

Plan A: Siehe auch Xtrabackup von Percona. Dies ermöglicht eine Online-Sicherung von InnoDB ohne nennenswerte Sperrung.

Plan B: Ein Slave kann gestoppt werden, und Sie können eine konsistente Sicherung auf verschiedene Arten durchführen (Dateien kopieren, mysqldump, xtrabackup usw.).

Plan C: LVM-Schnappschuss. Nach einigen kryptischen Einstellungen beträgt die Ausfallzeit für eine Sicherung weniger als eine Minute, unabhängig von der Größe der Datenbank. Sie stoppen mysqld, erstellen den Snapshot, starten mysqld neu und kopieren den Snapshot. Der letzte Schritt kann lange dauern, aber MySQL ist nicht ausgefallen.

Plan D: Momentaufnahme eines Slaves - keine Ausfallzeit.

19
Rick James

Ein paar Admin-Punkte zuerst: Stellen Sie eine Verbindung zu einem FTP her oder sind Sie eingeschaltet und es stirbt? Wenn ssh, verwenden Sie unbedingt screen, damit Sie nach dem Comcast-Absturz fortfahren können. Wenn ftp, dann stellen Sie sicher, dass Sie es/tar vor dem Senden komprimieren.

Versuchen Sie auch den Parameter --opt oder --quick

--opt Diese Option aktiviert eine Reihe zusätzlicher Optionen, um die Speicherauszugs- und Neuladevorgänge effizienter zu gestalten. Dies entspricht insbesondere der gemeinsamen Verwendung der Optionen --add-drop-table, --add-locks, --all, --quick, --extended-insert, --lock-tables und --disable-keys. Beachten Sie, dass diese Option die Ausgabe weniger portabel macht und von anderen Datenbanksystemen weniger wahrscheinlich verstanden wird.

--quick Diese Option weist mysqldump an, beim Lesen jeder Zeile vom Server eine Dump-Ausgabe zu schreiben, was für große Tabellen nützlich sein kann. Standardmäßig liest mysqldump alle Zeilen aus einer Tabelle in den Speicher, bevor die Ausgabe geschrieben wird. Für große Tabellen erfordert dies viel Speicher, was möglicherweise dazu führt, dass der Speicherauszug fehlschlägt.

15
David Hall

Ich hatte auch Probleme mit Timeouts während des Dumps großer Datenbanken. Ich habe es endlich gelöst, indem ich einzelne Befehle für jede Tabelle in der Datenbank gesendet und alles an eine Datei wie diese angehängt habe:

TABLES=`mysql -u $USER -p$PWD -Bse 'show tables' $DB`
for TABLE in $TABLES
do
    mysqldump -u $USER -p$PWD $DB $TABLE >> dump.sql
done
5
Patrick Heck

Ich denke, die Frage ist, wie man schneller aus den von mysqldump erstellten Dump-Dateien wiederherstellt, nicht mit einer anderen Sicherungslösung.

Sie können dies unter anderem tun, indem Sie Gruppen von Tabellen in Ihrem Schema erstellen und für jede Gruppe einen separaten DB-Benutzer erstellen. Anschließend können Sie mithilfe der MySQL-Berechtigungen nicht zulassen, dass Tabellen mit allen bis auf einen DB-Benutzer eingefügt werden.

Dies ist eine bewährte, schnelle, fast parallele Technik, aber nicht 100% sicher, wie lange die Wiederherstellung von großen Dumps wie 500G oder so dauern wird. Aber meiner bescheidenen Meinung nach braucht man etwas Paralleles. Überprüfen Sie den Link unten für ein Beispiel.

[Schnelle, parallele Wiederherstellung von SQL-Dumps (mysqldump) für MySQL] [1]

http://geeksww.com/tutorials/database_management_systems/mysql/tips_and_tricks/fast_parallel_restore_from_sql_dumps_mysqldump_for_mysql.php

"Schnelle, parallele Wiederherstellung von SQL-Dumps (mysqldump) für MySQL"

3
syed