it-swarm-eu.dev

Gibt es einen besseren Ausweg aus dem MySQL InnoDB-Protokoll "in der Zukunft"?

Ich habe diesen InnoDB-Fehler in MySQL 5.0. Mysqld wurde sauber gestoppt, aber ich konnte danach ib_logfile0 & ib_logfile1 verlieren. Nach einem sauberen Start hat InnoDB nun seine "Crash Recovery" durchgeführt. Ich habe das Geschäft innodb_force_recovery = 4 durchlaufen, eine blockierte MyISAM-Tabelle repariert, und jetzt ist die Replikation einsatzbereit. Große Zahlen bestätigt:

111116 15:49:36  InnoDB: Error: page 393457 log sequence number 111 561,760,232
InnoDB: is in the future! Current system log sequence number 70 3,946,969,851.
InnoDB: Your database may be corrupt or you may have copied the InnoDB
InnoDB: tablespace but not the InnoDB log files. See
InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html
InnoDB: for more information.

Dies ist auf einem Slave-Server. Der obige Fehler kommt zu Hunderten. Ich fand diese Antwort: "Daten im Wert von> 64 GB einfügen und löschen, damit die Protokollsequenznummer groß genug aufgeblasen wird".

http://forums.mysql.com/read.php?22,50163,50163#msg-50163

Diese magische Zahl von 64 GB stammt von 4 GB * 16, wobei die Innodb-Protokoll-Hauptzahl dieses Typen von 0 auf 15 erhöht werden musste. Die Mine geht von 70 auf 111 = 164 GB. Dies dauert 5 Tage. Ich werde weiter daran arbeiten, mein Skript zu beschleunigen und es parallel auszuführen, um dies zu beschleunigen. In der Zwischenzeit hoffe ich, dass jemand anderes eine bessere Antwort hat. Das ist dumm.

16
IcarusNM

Dies war eine ziemlich seltene Situation. Ich hoffe, dass ich nie wieder dort landen werde, mit einer InnoDB "Protokollsequenznummer liegt in der Zukunft!" Error. Aufgrund meiner besonderen Details war das Wiederherstellen/Wiederherstellen der Daten meines Servers ein letzter Ausweg. Einige Betrüger waren gute Ideen, aber am Ende entschied ich mich, mein Perl-Skript weiter zu verbessern, um dieses alberne Spiel zu spielen und so viele Gigs/Stunde wie möglich zu spielen. Was zum Teufel, es ist ein guter Systemstresstest.

Denken Sie daran: Das Ziel besteht darin, einen einzelnen Zähler ("Protokollsequenznummer") zu erhöhen, der irgendwo in den Kopfzeilen von ib_logfile und ib_logfile1 gespeichert ist. Dies dient dazu, InnoDB vorzutäuschen, damit ein offensichtlicher Zeitsprung ignoriert wird und das Leben weitergeht. Aber niemand weiß, wie man diese Nummer bearbeitet. Oder wenn sie es wissen, spricht niemand.

Hier ist mein Endprodukt. YMMV, aber die Verwendung der REPEAT-Funktion von mysql zum internen Generieren der Daten ist sehr effizient.

 #!/usr/bin/Perl
 use DBI;
 $table = shift || die;
 $dbh = DBI->connect("DBI:mysql:junk:Host=localhost", "user", "pass"); #Edit "junk" (DB name), user, and pass to suit.
 $dbh->do("DROP TABLE IF EXISTS $table");
 $dbh->do("CREATE TABLE $table (str TEXT) ENGINE=INNODB");
 $sth = $dbh->prepare("INSERT INTO $table (str) VALUES (REPEAT(?,1000000))");
 foreach (1..50) {
    $sth->execute('0123456789');   # 10 MB
 }
 $dbh->do("DELETE FROM $table");

Mein vorgeschlagenes Rezept:

  1. Erstellen Sie eine Junk-Datenbank
  2. Speichern Sie das obige Perl-Skript als junk.pl.
  3. Führen Sie junk.pl data1 und junk.pl data2 und junk.pl data usw. gleichzeitig für so viele CPU-Kerne aus wie Ihr Datenbankserver hat, um zu starten. Öffnen Sie mehrere Shells und wickeln Sie jeden Lauf in eine Bash-Schleife: while true; do date; junk.pl dataX; done.

Beobachten Sie, wie Ihr LSN wächst, vielleicht in einer anderen Schleife:

 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 3871092821
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 124 4209892586
 silly# echo "SHOW INNODB STATUS \G" | mysql -p'xxxxxx' | grep '^Log seq'
 Log sequence number 125 85212387

Die große Zahl ist eine vorzeichenlose 32-Bit-INT, die mit 4 GB umbrochen wird und die kleinere Zahl jedes Mal erhöht. In diesem Fall oben ist es nur von 124 auf 125 gerollt. Ihr Ziel ist im mysqld.log versteckt, das Sie überhaupt erst nach dieser lächerlichen Lösung gegoogelt hat. Sobald Sie diese Ziellinie überquert haben, ist es soweit! Schlag die Hörner! Lassen Sie das Konfetti los!

Seitenleiste: Dies hat einen interessanten Fehler in mysqld 5.0 mit REPEAT aufgedeckt: Wenn Sie auf 20 MB gehen, wird ein interner Zähler umgedreht und auf ~ 96 KB übertragen. Keine Warnung oder Fehler irgendwo. Ich wollte keine Zeit damit verschwenden, das aufzuspüren. 10 MB funktioniert super. Wenn Sie ein anderes Limit erreichen, kann es sich beschweren. Ich habe verschiedene innodb Puffer, die von der Standardeinstellung erhöht wurden. Nach Geschmack würzen. Sehen Sie sich wie immer mysqld.log in einem Fenster an.

10
IcarusNM

Sie haben drei (3) Optionen:

OPTION 01: Führen Sie eine Synchronisierung von Master zu Slave durch (Ausfallzeit auf dem Master)

  • Schritt 01: Führen Sie reset master; auf dem Master (Zaps Binary Logs)
  • Schritt 02: service mysql stop auf dem Master
  • Schritt 03: service mysql stop auf dem Sklaven
  • Schritt 04: rsync/var/lib/mysql vom Master zum Slave
  • Schritt 05: service mysql start auf dem Master
  • Schritt 06: Verwenden Sie das erste binäre Protokoll auf dem Master als Protokoll, um die Replikation zu starten. Verwenden Sie die Dateigröße dieses Protokolls als Position, von der aus die Replikation gestartet werden soll
  • Schritt 07: service mysql stop --skip-slave-start auf dem Sklaven
  • Schritt 08: Führen Sie den Befehl CHANGE MASTER TO aus, um die Replikation aus dem Protokoll und der Position einzurichten, die aus Schritt 06 ermittelt wurden
  • Schritt 09: Führen Sie start slave; auf dem Slave und lassen Sie die Replikation aufholen

OPTION 02: Führen Sie eine Synchronisierung von Master zu Slave durch (minimale Ausfallzeit auf dem Master)

  • Schritt 01: Führen Sie reset master; auf dem Master (Zaps Binary Logs)
  • Schritt 02: service mysql stop auf dem Sklaven
  • Schritt 03: rsync/var/lib/mysql vom Master zum Slave
  • Schritt 04: Wiederholen Sie Schritt 03, bis zwei aufeinanderfolgende Rsyncs dieselbe Zeit benötigen
  • Schritt 05: service mysql stop auf dem Master
  • Schritt 06: rsync/var/lib/mysql vom Master zum Slave
  • Schritt 07: service mysql start auf dem Master
  • Schritt 08: Verwenden Sie das erste binäre Protokoll auf dem Master als Protokoll, um die Replikation zu starten. Verwenden Sie die Dateigröße dieses Protokolls als Position, von der aus die Replikation gestartet werden soll
  • Schritt 09: service mysql stop --skip-slave-start auf dem Sklaven
  • Schritt 10: Führen Sie den Befehl CHANGE MASTER TO aus, um die Replikation aus dem Protokoll und der Position einzurichten, die in Schritt 08 ermittelt wurden
  • Schritt 11: Führen Sie start slave; auf dem Slave und lassen Sie die Replikation aufholen

OPTION 03: Verwenden Sie XtraBackup

Dieses Software-Tool erstellt nicht nur eine nicht aufdringliche Kopie eines laufenden Masters, sondern erstellt auch die entsprechenden ib_log-Dateien für Sie. Sie müssten die Replikation einrichten

Ich habe bereits zu diesem Thema auf StackExchange gepostet

Ich habe diese Dinge viele Male für das Webhosting-Unternehmen meines Arbeitgebers getan. Ein Kunde musste 3,7 TB bewegen und es dauerte ungefähr 16 Stunden. 64 GB sind im Vergleich sehr klein.

5
RolandoMySQLDBA

Ich fand heraus, dass es vielleicht eine coolere Möglichkeit gibt, dieses Problem bei partitionierten Tabellen zu lösen. Ich musste Partitionen von vor einigen Jahren löschen und einige für 2014 hinzufügen. Fast alle Partitionen melden diesen Fehler, also auch alte. Sehr böser Absturz.

Während also DROPPING old und REORGANIZE der MAXVALUE-Partition (die letzte) verwendet werden, werden neue Dateien erstellt, die in Ordnung sind, sodass ich immer weniger Warnungen erhalte. In der Zwischenzeit hilft es, den Protokollsequenzzähler zu erhöhen, sodass ich keine falschen Daten einfügen muss. Ich habe dies übrigens auf einem Master-Server ...

Also das:

ALTER TABLE Events DROP PARTITION p1530 , p1535 , p1540 , p1545 , 
p1550, p1555 , p1560 , p1565 , p1570 , p1575 , p1580 , p1585 , p1590 , 
p1595 , p1600 , p1605 , p1610 , p1615 , p1620 , p1625 , p1630 , p1635 , 
p1640 , p1645 , p1650 , p1655 , p1660 , p1665 , p1670 , p1675 , p1680 , 
p1685 , p1690 , p1695 , p1700 , p1705 , p1710 , p1715 , p1720 , p1725 , 
p1730 , p1735 , p1740 , p1745 , p1750 , p1755 , p1760 , p1765 , p1770 , 
p1775 , p1780 , p1785 , p1790 , p1795 , p1800 , p1805 , p1810 , p1815 , 
p1820 , p1825 , p1830 , p1835 , p1840;

Und das:

ALTER table Events REORGANIZE PARTITION p3000 INTO (
PARTITION p3500 VALUES LESS THAN (TO_DAYS('2013-01-01')),
PARTITION p3510 VALUES LESS THAN (TO_DAYS('2013-01-04')),
PARTITION p3520 VALUES LESS THAN (TO_DAYS('2013-01-07')),
PARTITION p3530 VALUES LESS THAN (TO_DAYS('2013-01-10'))
...
PARTITION p4740 VALUES LESS THAN (TO_DAYS('2014-01-08')),
PARTITION p9000 VALUES LESS THAN MAXVALUE)

Dadurch wird jede Partition in der Änderung effektiv gelöscht und mit einer temporären Kopie des Inhalts der darin enthaltenen Elemente neu erstellt. Sie können dies pro Tabelle tun, wenn Sie möchten. Meine Anwendung ermöglicht dies, sodass Sie sich keine Gedanken über synchronisierte Sicherungen usw. machen müssen.

Nun zum Rest der Tabelle, da ich nicht alle Partitionen im Prozess berührt habe, werden einige mit der Protokollsequenzwarnung für diejenigen belassen, die defekt sind aber und von dieser Reorganisationsaktion abgedeckt werde ich wahrscheinlich folgendes ausführen:

ALTER TABLE Events REBUILD PARTITION p0, p1;

oder das

ALTER TABLE Events OPTIMIZE PARTITION p0, p1;

Das brachte mich zum Nachdenken: Sie könnten dies mit einfachen Vanilla-Tabellen tun, Partitionen vorübergehend per Hash hinzufügen und später entfernen (oder sie behalten, ich kann Partitionen dringend empfehlen).

Ich benutze Mariadb jedoch nicht MySQL (also XtraDB)

Vielleicht hilft das jemandem. Ich leite es immer noch, soweit so gut. Das Ändern von ENGINE scheint ebenfalls den Job zu erledigen, daher bringe ich es zwischen MyIsam und ihnen zurück zu InnoDB.

Es ist ziemlich logisch, wenn Sie ENGINE ändern, verschwindet die Tabelle aus innodb, sodass dies kein Problem mehr darstellt.

ALTER TABLE Events ENGINE=MyISAM;
ALTER TABLE Events ENGINE=InnoDB;

es scheint hier zu funktionieren. Ich kann einige Dinge in partitionierten Tabellen bestätigen:

  • ALTER TABLE xyz ENGINE = InnoDB ist sehr langsam, für Aria (Mariadb) doppelt so schnell, aber im Allgemeinen eine langsame Methode, um den Protokollsequenzzähler zu erhöhen
  • ALTER TABLE xyz REBUILD PARTITION ALL ist der schnellste Weg, um die Tabellen zu "reparieren" und den Zähler zu erhöhen
  • ALTER TABLE xyz ANALYZE PARTITION ALL ist langsam mit der ersteren verglichen und schreibt keine Partitionen neu, die sich als in Ordnung herausstellen. REBUILD stellt sicher, dass ein temporäres Tabellenschema neu geschrieben wird.

Ich habe die letzten an mehreren Tischen verwendet. Die Warnungen treten auf, wenn versucht wird, die Dateien zu öffnen, und es gibt eine für jede Partitionsdefinition, die mit Gegenproblemen geöffnet wird. Heute fast über den Ladentisch für die letzten Tische gerollt. Ich denke, wenn alles verarbeitet ist, muss man die Binärprotokolle leeren.

pdate: Ich kann ein paar Dinge abschließen, jetzt habe ich es geschafft, dieses Problem zu lösen.

  • Mein Absturz wurde durch die Neuorganisation von Partitionen in einer Tabelle im Aria-Format (MariaDB) verursacht.
  • (für mich) ein Neuerstellen der Partitionen hat am besten und schnellsten funktioniert, um den Sequenzzähler hoch zu bringen. Das Ändern des Motors ist langsam und Sie müssen es zweimal tun, um innodb zu beeinflussen. Der Wechsel zu innoDB ist im Vergleich zu MyIsam oder Aria ziemlich langsam.
  • Ich habe ein Upgrade auf MariaDB 5.3 und nicht auf 5.5 (war: 5.2) durchgeführt und es funktioniert einwandfrei. Ich denke, es gibt viel zu viele Probleme mit Arien, Partitionen in 5.5 (und bestätigten Fehlern), um diese Kombination zu verwenden.
  • Es sollte wirklich eine bessere Möglichkeit geben, den Protokollsequenzzähler zurückzusetzen.
2
Glenn Plas