it-swarm.com.de

Suchen und Beheben von InnoDB-Indexbeschädigungen

Ich habe gestern ein neues Problem mit einer meiner MySQL 5.5-Slave-DBs festgestellt, die auf EC2 in AWS ausgeführt wird. Die Datenbank wurde aus einem Snapshot eines anderen Slaves erstellt. Die Daten sind korrekt, aber für mindestens eine Tabelle gibt ein Sekundärindex unvollständige Ergebnisse zurück. Das Abfragen einer untergeordneten Tabelle anhand der übergeordneten ID ergab 498 Zeilen, wenn 504 zurückgegeben werden sollten. Das Abfragen der fehlenden 6 Zeilen nach dem Primärschlüssel funktionierte, und die richtige übergeordnete ID wurde zurückgegeben, sodass das Problem beim sekundären Index liegt.

Dieses Problem ist für mich sehr besorgniserregend, da ich vermutlich auch dann, wenn alle Daten auf dem Slave mit dem Master übereinstimmen, bei einigen auf dem Slave ausgeführten Abfragen immer noch falsche Ergebnisse erhalte.

Meine Brute-Force-Lösung bestand darin, den gesamten Tisch folgendermaßen neu aufzubauen:

alter table my_table engine = innodb;

Damit wurde das Problem für diese bestimmte Tabelle behoben, aber ich habe folgende Fragen:

1) How can I determine if other tables have similar index corruption?
2) What's the most efficient way to fix the corrupt indexes?

Ich habe online einige gute Ressourcen zum Auffinden und Beheben von InnoDB-Datenbeschädigungen gefunden, aber nichts Relevantes für InnoDB-Indexbeschädigungen gefunden.

Ich habe im MySQL-Fehlerprotokoll nachgesehen und keine rauchende Waffe gefunden. Ich habe einige störende InnoDB-Fehler gefunden. Ich gehe davon aus, dass dies ein separates Problem ist, aber es könnte damit zusammenhängen:

130109  9:46:41  InnoDB: unable to find a record to delete-mark
InnoDB: Tuple DATA Tuple: 2 fields;
 0: len 4; hex 04af1f21; asc    !;;
 1: len 4; hex 0a1c03bd; asc     ;;

InnoDB: record PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 04af1f21; asc    !;;
 1: len 4; hex 0a052a77; asc   *w;;
7
Ike Walker

Vielen Dank an Rolando und Michael für Ihre Antworten.

Um den Kreis zu schließen, habe ich folgende Antwort auf meine ursprünglichen Fragen gefunden:

  • F: Wie kann ich feststellen, ob andere Tabellen eine ähnliche Indexbeschädigung aufweisen?
  • A: Verwenden Sie CHECK TABLE. Ich rannte mysqlcheck -c in allen relevanten InnoDB-Tabellen, um herauszufinden, welche eine Indexbeschädigung aufwiesen

  • F: Was ist der effizienteste Weg, um die beschädigten Indizes zu reparieren?

  • A: Verwenden Sie OPTIMIZE TABLE, um die InnoDB-Tabelle mit beschädigten Indizes neu zu erstellen. Dies führt zu einer vollständigen Tabellenwiederherstellung, die die Beschädigung behebt.
14
Ike Walker

Möglicherweise haben Sie die einfachste Lösung, die es gibt. Ich würde jedoch gerne einige Dinge klarstellen:

Das Erstellen eines Snapshots mit einer laufenden MySQL-Instanz kann sich auf die eine Datei auswirken, die für die Manipulation des Sekundärindex verantwortlich ist: ibdata1.

Der Systemtabellenbereich ibdata1 Ist die Heimat von 7 Klassen von InnoDB-Informationen

  • Datenseiten (falls innodb_file_per_table deaktiviert)
  • Indexseiten (falls innodb_file_per_table deaktiviert)
  • Datenwörterbuch (Enthaltene Liste der Tabellen und ihrer TableSpace-IDs)
  • Double Write Buffer (Bietet Prüfsummeninformationen zur Verhinderung von Datenbeschädigung)
  • Puffer einfügen (Änderungen an Sekundärindizes)
  • Protokolle wiederholen
  • Protokolle rückgängig machen
  • Bilddarstellung

Die Schlüsselklassen, über die ich mir Sorgen machen würde, sind der Double Write Buffer und der Insert Buffer. Wenn Sie einen Live-Snapshot mit einem dieser nicht ordnungsgemäß geschriebenen Snapshots erstellen, wird die Daten beschädigt.

Wenn Sie FLUSH TABLES WITH READ LOCK; stoppen, werden die Schreibvorgänge in ibdata1 nicht angehalten, wie man denken würde. Ich habe vorher über dieses Thema geschrieben . Früher dachte ich, dass dies der Fall war, bis DBA.SE-Mitglied @ShlomiNoach darauf hinwies.

Denken Sie an den InnoDB Buffer Pool. Sie müssten jede schmutzige Seite herausspülen, um alles auf die Festplatte zu bringen. Im Folgenden werden alle verschmutzten Seiten pro Tabelle herausgedrückt:

  • SET GLOBAL innodb_fast_shutdown = 0; Gefolgt von service mysql stop
  • SET GLOBAL innodb_max_dirty_pages_pct = 0; Und warten Sie, bis 1% des Pufferpools verschmutzt ist
  • mysqldump

Vergessen Sie auch nicht, dass Binärprotokolle und Relay-Protokolle zum Löschen vom Betriebssystem abhängen.

Ein EC2-Snapshot ist in dieser Hinsicht nicht MySQL-Aware, nicht mehr als ein LVM-Snapshot. Aus diesem Grund verfügt Backup-Software wie CDPs R1Soft für solche Gelegenheiten über ein MySQL-Modul.

Im Gegensatz dazu ist eine Amazon RDS MYSQL-Instanz für solche InnoDb-zentrierten Szenarien bekannt und entwickelt. Nur wenn in der RDS-Instanz aktive MyISAM-Tabellen vorhanden sind, wäre FLUSH TABLES WITH READ LOCK; Ein notwendiges Übel, um manuell auszuführen .

In Bezug auf Ihre ursprüngliche Frage haben Sie beim Ausführen von ALTER TABLE my_table ENGINE=InnoDB; Einfach Indexseiten neu erstellt, die von Datenseiten der Tabelle gelesen wurden, wobei höchstwahrscheinlich der Einfügepuffer ibdata1 umgangen wurde. Deshalb hat das bei Ihnen funktioniert.

Wenn Sie einen mysqldump mit --single-transaction --master-data=1 Auf dem Master ausführen können, scp den mysqldump an den Slave und ohne finanzielle Kosten. Dies wäre eine sicherere Methode zum Einrichten des EC2-Slaves.

Wenn Sie den Schnappschuss machen müssen, tun Sie dies bitte auf dem Slave:

  • Führen Sie SET GLOBAL innodb_fast_shutdown = 0;
  • service mysql stop
  • Mach deinen Schnappschuss
  • service mysql start
  • Füge innodb_fast_shutdown zu /etc/my.cnf Hinzu.

Zusätzliche Informationen: Je kleiner ib_logilfe0 und ib_logfile1 sind, desto schneller wird das Herunterfahren.

Ich hoffe das erklärt viel.

UPDATE 2013-01-14 10:36 EDT

Sie haben kürzlich im Kommentarbereich gefragt

wie kann ich feststellen, ob eine Datenbank eine Indexbeschädigung aufweist?

Denken Sie daran, dass Sie EC2 und nicht RDS verwenden. Mit RDS ist Amazon für den ganzheitlichen Status der VM und der MySQL-Instanz verantwortlich. Mit EC2 ist Amazon für den VM) verantwortlich. Der ganzheitliche Status Die MySQL-Instanz liegt jetzt bei Ihnen. Möglicherweise möchten Sie die Datenbank auf RDS portieren, da sie mit zusätzlichen Funktionen ausgestattet ist, um sich vor einer solchen Beschädigung zu schützen.

8
RolandoMySQLDBA