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

16

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 "Absturzwiederherstellung" durchgeführt. Ich habe das Geschäft mit innodb_force_recovery = 4 durchgearbeitet, eine hängengebliebene MyISAM-Tabelle repariert, und abgesehen davon ist die Replikation jetzt einsatzbereit. Große Zahlen verpflichtet:

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 spuckt zu Hunderten aus. Ich fand diese Antwort: "Einfügen und Löschen von Daten im Wert von> 64 GB, damit die Protokollfolgenummer groß genug aufgepumpt 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 "Hauptzahl" des Innodb-Protokolls dieses Typen von 0 auf 15 erhöht werden musste. Die Mine wird 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.

IcarusNM
quelle
Eine vielversprechende Antwort: "Wenn es sich um einen Slave-Server handelt, ist es die beste Lösung, die Datenbank beiseite zu schieben und einen neuen Snapshot vom Master zu installieren." Leider gibt es 20.000 Tabellen in 25 Datenbanken, eine Mischung aus MyISAM und InnoDB, die rund um die Uhr in Betrieb sind. Es würde zu lange dauern, alles herunterzufahren und eine neue vollständige Replikation durchzuführen, bevor die Replikation erneut gestartet wird.
IcarusNM
4
Ich habe jetzt diese 8-Kern-Maschine in einem sinnlosen Rennen auf den Knien, um 164 Datenmengen zu erstellen und zu löschen. Die einzige Alternative, die ich höre, ist, alles an diesem Sklaven zu zerstören und von vorne zu beginnen. Alle, um effektiv eine Zahl in zwei Dateien zu ändern. Es gibt sicherlich einen InnoDB-Ingenieur mit einem Pro-Tipp. Hat jemand jemals ib_logfile0 in Emacs geöffnet, die magische Zahl in hex gefunden und nur geändert?
IcarusNM
Hier ist ein großartiger Artikel über einige Möglichkeiten, dies zu tun. Percona ist definitiv die Autorität auf MySQL. percona.com/blog/2013/09/11/…
jbrahy

Antworten:

10

Dies war eine ziemlich seltene Situation. Ich hoffe, dass ich nie wieder dort landen werde, mit einer InnoDB "log sequence number is in the future!" Error. Aufgrund meiner besonderen Details war das Neuerstellen / Wiederherstellen der Daten meines Servers ein letzter Ausweg. Einige Tricks waren gute Ideen, aber am Ende habe ich beschlossen, mein Perl-Skript weiter zu verbessern, um dieses alberne Spiel zu spielen und so viele Auftritte pro Stunde wie möglich zu absolvieren. Was soll's, es ist ein guter Systemstresstest.

Denken Sie daran: Das Ziel besteht darin, einen einzelnen Zähler ("log sequence number") zu erhöhen, der irgendwo in den Headern von ib_logfile0 und ib_logfile1 gespeichert ist . Dies dient dazu, InnoDB so auszutricksen, dass es einen offensichtlichen Zeitsprung ignoriert und mit dem Leben weitermacht. Aber niemand weiß, wie man diese Nummer bearbeitet. Oder wenn sie es wissen, redet niemand.

Hier ist mein Endprodukt. YMMV, aber die interne Generierung der Daten mit der REPEAT-Funktion von mysql 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 Rezeptvorschlag:

  1. Erstellen Sie eine Junk-Datenbank
  2. Speichern Sie die oben Perl - Skript als junk.pl .
  3. Führen Sie junk.pl data1 und junk.pl data2 und junk.pl data3 usw. gleichzeitig aus, um so viele CPU-Kerne wie Ihr Datenbankserver zu starten. Öffnen Sie mehrere Schalen und wickeln jeden Lauf in einer 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 jeweils kleinere Zahl erhöht. In diesem Fall oben ist es nur von 124 auf 125 gewälzt. Ihr Ziel ist im mysqld.log versteckt , das Sie von Anfang an zum Googeln für diese lächerliche Lösung geschickt hat. Sobald Sie die Ziellinie überquert haben, ist es soweit! Schlag die Hörner! Lassen Sie die Konfetti los!

Sidebar: Dies deckte einen interessanten Fehler in mysqld 5.0 mit REPEAT auf: Wenn Sie zu 20 MB wechseln, wird ein interner Zähler umgedreht und ein Rollover auf ~ 96 KB ausgeführt. Keine Warnung oder Fehler überall. Ich wollte keine Zeit damit verschwenden, das aufzuspüren. 10 MB funktioniert super. Wenn Sie ein anderes Limit erreichen, kann dies zu Beschwerden führen. Ich habe verschiedene Innodb- Puffer von Standard erhöht. Nach Geschmack würzen. Wie immer sehen Sie mysqld.log in einem Fenster.

IcarusNM
quelle
Check this out percona.com/blog/2013/09/11/…
Jonas Stensved
Danke Jonas; das ist interessant. Ich denke, ich kann mich an meine obige Methode halten. Er zeigt die Verwendung von gdb gegen die Ausführung von mysqld, die ich wahrscheinlich niemals riskieren würde. Aber auch dort gute Informationen.
IcarusNM
Aus irgendeinem seltsamen Grund erhalte ich mit MariaDB nicht die Protokollsequenznummern "Small Number [Space] Big Number", sondern nur eine "Big Number". Leider hat diese Methode bei mir nicht funktioniert. Nun, natürlich wird das Protokoll aktualisiert, ich weiß nur nicht, wann ich aufhören soll!
Gwyneth Llewelyn
5

Sie haben drei (3) Möglichkeiten:

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

  • Schritt 01: reset master;Auf dem Master ausführen (Zaps Binary Logs)
  • Schritt 02: service mysql stopAuf dem Master
  • Schritt 03: service mysql stopAuf den Sklaven
  • Schritt 04: rsync / var / lib / mysql vom Master zum Slave
  • Schritt 05: service mysql startAuf dem Master
  • Schritt 06: Verwenden Sie das erste Binärprotokoll auf dem Master als Protokoll, um die Replikation zu starten. Verwenden Sie die Dateigröße dieses Protokolls als Position, um die Replikation zu starten
  • Schritt 07: service mysql stop --skip-slave-startAuf den 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;den Slave aus 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: reset master;Auf dem Master ausführen (Zaps Binary Logs)
  • Schritt 02: service mysql stopAuf den 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 stopAuf dem Master
  • Schritt 06: rsync / var / lib / mysql vom Master zum Slave
  • Schritt 07: service mysql startAuf dem Master
  • Schritt 08: Verwenden Sie das erste Binärprotokoll auf dem Master als Protokoll, um die Replikation zu starten. Verwenden Sie die Dateigröße dieses Protokolls als Position, um die Replikation zu starten
  • Schritt 09: service mysql stop --skip-slave-startAuf den Sklaven
  • Schritt 10: Führen Sie den Befehl CHANGE MASTER TO aus, um die Replikation aus dem Protokoll und der Position, die aus Schritt 08 ermittelt wurden, einzurichten
  • Schritt 11: Führen Sie start slave;den Slave aus und lassen Sie die Replikation aufholen

OPTION 03: Verwenden Sie XtraBackup

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

Ich habe zu diesem Thema schon einmal im StackExchange gepostet

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

RolandoMySQLDBA
quelle
In OPTION 02 Schritt 05 sagen Sie, dass der Master gestartet werden soll. Wann wurde es gestoppt? Rsync auf einem Live-Master ist mutig. Ich bin beeindruckt. Und zum Glück benutze ich innodb_file_per_table. Aber irgendwann müssen Sie die Kugel beißen und den Master so lange anhalten, bis ein abschließender rsync ausgeführt wird, bevor Sie mit der Replikation beginnen. Das ist eine Möglichkeit, auf die ich zurückgreifen kann, aber dies ist ein sehr aktives DBMS. Und ich werde XtraBackup nach meinen Informationen durchsuchen.
IcarusNM
@ IcarusNM: Ah, Tippfehler. Ich habe es korrigiert. Danke !!!
RolandoMySQLDBA
OPTION 02 könnte wahrscheinlich noch etwas Arbeit gebrauchen. ZB sollten Sie Schritt 2 vor Schritt 1 ausführen. Sie möchten wahrscheinlich irgendwo einen RESET SLAVE. Tippfehler in Schritt 4. Und Sie sagen in Schritt 5 "Erstes Binärprotokoll", aber Sie meinen wirklich "Nur" oder "Letztes" Binärprotokoll. Und Sie sollten mysqlbinlog verwenden, um die Protokollpositionen und nicht die Dateigröße zu ermitteln. Und all dies wird immer noch nicht funktionieren, wenn Sie den Master nicht irgendwann stoppen. Es ist bestenfalls riskant, eine Log-Position / -Zeit auf den Zeitpunkt zu setzen, an dem ein Rsync beendet wurde.
IcarusNM
Ich mache seit 4 Jahren OPTION 2 mit DB Hosting-Kunden, die Daten im TeraByte-Bereich haben. Es funktioniert immer gegen einen laufenden Server. Der einzige wirkliche Fehler, den du machen könntest, ist der Sklave. Dieser Fehler liegt darin, ob die Replikation ordnungsgemäß eingerichtet wurde oder nicht. Darüber hinaus RESET SLAVEist dies hilfreich, insbesondere wenn Sie viele GB Relay-Protokolle angehäuft haben. Denken Sie nach dem rsync-Vorgang und der Wiederherstellung der Replikation daran, dass der Befehl CHANGE MASTER TO auch die Relay-Protokolle für Sie löscht.
RolandoMySQLDBA
mmm ... seltsam. Ich habe meinen Slave mit xtrabackup eingerichtet (wie immer) und trotzdem diese Log-Fehler erhalten (percona mysql 5.5.x) ... anscheinend ist bei diesem Slave etwas schief gelaufen und ich muss es erneut tun.
harald
2

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.

Wenn Sie also die alte Partition DROPPEN und REORGANIZE der MAXVALUE-Partition (die letzte) verwenden, 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 das passiert auf einem Master-Server übrigens ...

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)

Auf diese Weise wird jede Partition in der Änderung gelöscht und mit einer temporären Kopie des Inhalts der vorhandenen Partition neu erstellt. Sie können dies pro Tabelle tun, wenn Sie möchten. Meine Anwendung lässt dies zu, sodass Sie sich nicht um synchronisierte Sicherungen usw. kümmern müssen.

Nun zum Rest der Tabelle, da ich nicht alle Partitionen in dem Prozess berührt habe, werden einige mit der Protokollsequenz-Warnung belassen, für diejenigen, die defekt sind , aber von dieser Reorganisationsaktion abgedeckt werden, 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 Vanilletabellen tun, temporär Partitionen per Hash hinzufügen und später entfernen (oder 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 zu funktionieren, 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 ein paar Dinge auf partitionierten Tabellen bestätigen:

  • ALTER TABLE xyz ENGINE = InnoDB ist sehr langsam, Aria (Mariadb) doppelt so schnell, aber im Allgemeinen ein langsamer Weg, 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 im Vergleich zu früheren Partitionen und schreibt Partitionen, die sich als in Ordnung herausstellen, nicht neu. REBUILD sichert ein Umschreiben in ein temporäres Tabellenschema zu.

Die letzten habe ich 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 Leistungsindikatorproblemen geöffnet wird. Fast über die Ladentheke gerollt heute für die letzten Tische. Ich denke, wenn alles einmal abgearbeitet ist, muss man die Binärlogs leeren.

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

  • Mein Absturz wurde durch das Reorganisieren von Partitionen in einer Tabelle im Aria-Format (MariaDB) verursacht.
  • (für mich) hat es am besten und schnellsten geklappt, einen Neustart der Partitionen durchzuführen, um den Sequenzzähler auf den neuesten Stand zu bringen. Das Ändern des Motors ist langsam und Sie müssen es zweimal tun, um innodb zu beeinflussen. Änderungen an innoDB sind im Vergleich zu MyIsam oder Aria recht langsam.
  • Ich habe ein Upgrade auf MariaDB 5.3 und nicht auf 5.5 (bisher: 5.2) durchgeführt und es funktioniert einwandfrei. Ich denke, es gibt viel zu viele Probleme mit Aria, 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.
Glenn Plas
quelle
Unter MariaDB können Sie alle Tabellen mit USE INFORMATION_SCHEMA; SELECT CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` REBUILD PARTITION ALL;") AS MySQLCMD AS MySQLCMD FROM TABLES;(Quelle: dba.stackexchange.com/questions/35073/… ) schnell ändern und in eine Datei einbinden , die als Folge von Befehlen ausgeführt werden soll.
Gwyneth Llewelyn