MySQL : InnoDB et index corrompu

de | 2017-03-31

Contexte

Depuis le passage en innodb, le serveur tombe en erreur car des pages d’indexes sont corrompues.

Il héberge une application de supervision dont les écritures sont intensives et se concentrent sur deux tables. Le système d’exploitation est une VM Centos 7.2. Le file system  de données est formaté en ext4 et monté avec les options suivantes : « defaults,noatime,nodiratime,nobarrier ». Les binaires sont mariadb-server 10.0.25, ce qui commence à être un peu ancien mais c’est la version de la distribution.

Au contraire de MyIsam, InnoDB est un vrai moteur transactionnel et bloque en cas de doute. Le SGBD est alors tué par un signal 6 et automatiquement relancé par le script « mysqld_safe, comme le ferait PostgreSQL dans les mêmes circonstances.

La corruption de page est un problème récurrent sur cette plate-forme et ni le changement de file system (de XFS vers ext4), ni le changement de moteur (de MyIsam vers InnoDB) ne nous ont débarrassé de ces plantages aléatoires et intempestifs.

Faites nous confiance pour mettre à jour cette article si nous finissons par avoir une explication convaincante mais à l’heure où nous rédigeons, c’est le flou total.

Cependant, les corruptions arrivant dans des cas plus simples que le notre, voyons comment les corriger…

Message d’erreur

2017-03-19 17:09:25 7fddd30d2700  InnoDB: Assertion failure in thread 140590705354496 in file btr0cur.cc line 293
InnoDB: Failing assertion: sibling_mode == RW_NO_LATCH || btr_page_get_next(get_block->frame, mtr) == page_get_page_no(page)
InnoDB: We intentionally generate a memory trap.
InnoDB: Submit a detailed bug report to http://bugs.mysql.com.
InnoDB: If you get repeated assertion failures or crashes, even
InnoDB: immediately after the mysqld startup, there may be
InnoDB: corruption in the InnoDB tablespace. 

… Suivi d’un long stackstrace et de quelques conseils.

Pages d'index InnoDB Soigneusement Rangées Sur Disque (Archive)

Pages d’index InnoDB Soigneusement Rangées Sur Disque (Archive)

Actions

1) Valider la corruption
Stop / start du service : en root “service mariadb restart”. Si l’erreur est vraiment sur disque et non en mémoire, elle ré-apparaîtra dès la vérification de lancement.

2) Vérification des fichiers *.ibd, serveur arrêté

for f in $(find /var/lib/mysq/ -name "*.ibd"); do
echo "-- doing $f"
innochecksum -v $f
done

Ce n’est qu’une vérification mais indique si d’autres tables sont affectées.

3) Corriger la corruption

Pour réparer, connecté à MySQL :

check table nom_base.nom_table;

Qui affiche quelque chose comme ça :

<pre>+-----------------------+-------+----------+---------------------------------------------------+
| Table                 | Op    | Msg_type | Msg_text                                          |
+-----------------------+-------+----------+---------------------------------------------------+
| base1.table1 | check | Warning  | InnoDB: Index "index1" is marked as corrupted           |
| base1.table1 | check | Warning  | InnoDB: Index "index2" is marked as corrupted |
| base1.table1 | check | Warning  | InnoDB: Index "index3" is marked as corrupted           |
| base1.table1 | check | error    | Corrupt                                                    |
+-----------------------+-------+----------+---------------------------------------------------+</pre>

Passer la commande de correction : “optimise table nom_table;”. Exemple:

optimize table Base1.table1;

Qui affiche quelque chose comme :

ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    20
Current database: *** NONE ***

+-----------------------+----------+----------+-------------------------------------------------------------------+
| Table                 | Op       | Msg_type | Msg_text                                                          |
+-----------------------+----------+----------+-------------------------------------------------------------------+
| base1.table1 | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| base1.table1 | optimize | status   | OK                                                                |
+-----------------------+----------+----------+-------------------------------------------------------------------+

Logo Presque Officiel Du Serveur MySQL

Logo Presque Officiel Du Serveur MySQL

« ERROR 2006 (HY000): MySQL server has gone away » : un signe très sûr que vous avez des problèmes (ce message à forte teneur en expertise vous est gracieusement offert par la rédaction).

Plus concrètement,  il s’agit d’une erreur coté client : la requête remonte une quantité de lignes supérieure au paramètre « max_allowed_packet », qui est de 100Mo maximum. Le client se reconnecte automatiquement mais la commande ne s’est pas forcément terminée.

Si cela ne fonctionne pas, il ne vous reste que le « truncate » quand c’est possible – quand les données sont sacrifiables – ou bien le rechargement de la table.

Conclusion

A l’heure où cet article est rédigé, nous ne pouvons pas dire d’un ton assuré, le menton vaillant levé sans crainte vers l’avenir, que nous ne reverrons pas pas ces erreurs car elles semblent liées à nos machines. Nous avons plusieurs suspects : des clichés de VM (type live snapshots donc fichiers ouverts) mais d’autres machines sont sauvegardées de cette manière et ne souffrent pas du même problème (cependant elles sont en Centos 6); ou bien une option de montage telle que « nobarrier », puisque celui-ci joue un rôle au niveau de l’écriture du cache.

Mais nous risquons surtout de faire face à l’urgence et de déplacer toute la base vers une nouvelle machine donc nous n’aurons pas le fin mot du mystère de l’histoire.

Si vous, lecteur, avez une explication, faites-en nous part dans les commentaires (n’hésitez pas : nous aimerions bien modérer autre chose que du spam russe !) et permettez nous de retirer un nœud de la pelote d’interrogations qui nous tient éveillé au milieu de la nuit.

D’avance, merci.

PS : en bonus, pour ceux que ça intéresse, un magnifique schéma de l’architecture Innodb que l’on verrait bien en poster ou en T-Shirts. Le lien pointe vers Scribd.com mais le schéma est probablement dans la documentation officielle ou sur le site de Percona qui fournit la version XtraDB de InnoDB, intégrée dans MariaDB. Tout ceci fait beaucoup de « DB ».

 

Des problèmes ? des questions ? Exprimez-vous ! Les commentaires sont ouverts. Coquilles et fautes de grammaires sont notre lot quotidien : signalez-les nous à m.capello@dbsqware.com

Crédit photo : Nice Matin et ImgFlip Meme generator (on a les sources qu’on mérite…)