web-dev-qa-db-fra.com

Recherche et correction de la corruption d'index InnoDB

Hier, j'ai rencontré un nouveau problème avec l'une de mes bases de données esclaves MySQL 5.5 qui fonctionne sur EC2 dans AWS. La base de données a été créée à partir d'un instantané d'un autre esclave. Les données sont correctes, mais pour au moins une table, un index secondaire renvoie des résultats incomplets. L'interrogation d'une table enfant par l'ID parent renvoyait 498 lignes alors qu'elle aurait dû en retourner 504. L'interrogation des 6 lignes manquantes par clé primaire a fonctionné, et l'ID parent correct a été renvoyé, donc le problème est avec l'index secondaire.

Ce problème est très préoccupant pour moi, car même si toutes les données sur l'esclave correspondent au maître, j'obtiendrai toujours des résultats incorrects de certaines requêtes exécutées sur l'esclave.

Ma solution de force brute était de reconstruire la table entière comme ceci:

alter table my_table engine = innodb;

Cela a résolu le problème pour ce tableau spécifique, mais je me retrouve avec les questions suivantes:

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

J'ai trouvé de bonnes ressources en ligne pour trouver et corriger la corruption des données InnoDB, mais je n'ai trouvé rien de pertinent pour la corruption d'index InnoDB.

J'ai regardé dans le journal des erreurs MySQL et je n'ai pas trouvé d'arme à feu. J'ai trouvé des erreurs InnoDB troublantes. Je suppose que c'est un problème distinct, mais cela pourrait être lié:

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

Merci Rolando et Michael pour vos réponses.

Pour boucler la boucle, voici la réponse que j'ai trouvée pour mes questions originales:

  • Q: Comment puis-je déterminer si d'autres tables ont une corruption d'index similaire?
  • A: tilisez CHECK TABLE. L'Iran mysqlcheck -c sur toutes les tables InnoDB pertinentes pour découvrir celles qui avaient une corruption d'index

  • Q: Quelle est la manière la plus efficace de corriger les index corrompus?

  • A: tilisez OPTIMIZE TABLE pour reconstruire la table InnoDB qui a des index corrompus. Cela provoque une reconstruction complète de la table qui corrige la corruption.
14
Ike Walker

Vous avez peut-être la solution la plus simple qui soit. Cependant, j'aimerais clarifier certaines choses:

Faire un instantané avec une instance MySQL en cours d'exécution pourrait affecter le seul fichier responsable de la manipulation d'index secondaire: ibdata1.

L'espace de table système ibdata1 est le foyer de 7 classes d'InnoDB Information

  • Pages de données (si innodb_file_per_table est désactivé)
  • Pages d'index (si innodb_file_per_table est désactivé)
  • Dictionnaire de données (liste des tables incluse et leurs ID TableSpace)
  • Double tampon d'écriture (fournit des informations de somme de contrôle pour empêcher la corruption des données)
  • Insérer un tampon (modifications apportées aux index secondaires)
  • Rétablir les journaux
  • Annuler les journaux
  • Représentation picturale

Les classes pivots dont je m'inquiéterais sont le double tampon d'écriture et le tampon d'insertion. Faire un instantané en direct avec l'un ou l'autre de ceux-ci n'est pas correctement écrit introduira une corruption des données.

Faire FLUSH TABLES WITH READ LOCK; n'arrête pas les écritures sur ibdata1 comme on pourrait le penser. J'ai déjà écrit sur ce sujet . Je pensais que c'était le cas, jusqu'à ce que collègue DBA.SE @ShlomiNoach .

Pensez au pool de tampons InnoDB. Vous devrez en vider chaque page sale pour que tout soit mis au repos sur le disque. Les éléments suivants forcent toutes les pages sales sur une base par table:

  • SET GLOBAL innodb_fast_shutdown = 0; suivi par service mysql stop
  • SET GLOBAL innodb_max_dirty_pages_pct = 0; et attendez que 1% du pool de tampons soit sale
  • mysqldump

N'oubliez pas non plus que les journaux binaires et les journaux de relais dépendent du système d'exploitation pour le vidage.

Un instantané EC2 n'est pas compatible avec MySQL à cet égard, pas plus qu'un instantané LVM ne le serait. C'est pourquoi un logiciel de sauvegarde tel que R1Soft de CDP a un module MySQL pour de telles occasions.

Au contraire, une instance Amazon RDS MYSQL est compatible et conçue pour de tels scénarios centrés sur InnoDb. Uniquement s'il y a des tables MyISAM actives dans l'instance RDS, FLUSH TABLES WITH READ LOCK; être un mal nécessaire pour effectuer manuellement .

En ce qui concerne votre question d'origine, lorsque vous avez exécuté ALTER TABLE my_table ENGINE=InnoDB; vous avez simplement reconstruit les pages d'index en lisant les pages de données de la table, en contournant très probablement le tampon d'insertion ibdata1. C'est pourquoi cela a fonctionné pour vous.

Si vous pouvez faire un mysqldump avec --single-transaction --master-data=1 sur le maître, scp le mysqldump à l'esclave, et faites-le sans frais financiers, ce serait une méthode plus sûre pour configurer l'esclave EC2.

Si vous devez faire l'instantané, veuillez le faire sur l'esclave:

  • Courir SET GLOBAL innodb_fast_shutdown = 0;
  • service mysql stop
  • Faites votre instantané
  • service mysql start
  • Ajoutez innodb_fast_shutdown à /etc/my.cnf

Informations supplémentaires: Plus ib_logilfe0 et ib_logfile1 sont petits, plus l'arrêt est rapide.

J'espère que cela explique beaucoup de choses.

MISE À JOUR 2013-01-14 10:36 EDT

Vous avez récemment demandé dans la section commentaire

comment savoir si une base de données présente une corruption d'index?

N'oubliez pas que vous utilisez EC2 et non RDS. Avec RDS, Amazon est responsable de l'état holistique de VM et de l'instance MySQL. Avec EC2, Amazon est responsable de VM uniquement. L'état holistique de l'instance MySQL vous appartient désormais. Vous souhaiterez peut-être porter la base de données sur RDS car elle est livrée avec des cloches et des sifflets supplémentaires pour vous prémunir contre une telle corruption.

8
RolandoMySQLDBA