MySQL: « table full » avec des tables en mémoire

de | 2016-11-11

Aujourd’hui, un bref article sur un problème rencontré récemment avec un traitement s’exécutant sur MySQL (1). Cela nous permettra au passage de montrer quelques commandes utiles pour positionner la valeur des variables du serveur.

L’erreur

Tous les matins, une extraction … hum, comment le dire poliment ?.. expérimentale (voilà, c’est bien) se lance et échoue. Dans le log général (« show variables like ‘log_error’; » si vous le cherchez).

161030  4:41:57 [ERROR] mysqld: The table 't_putAllThings' is full

La recherche

Premier réflexe : est-ce un problème d’espace disque ? Non. Du gigaoctet libre à perte de vue.

Deuxième réflexe : De quoi est fait cette table ?

Des colonnes, des indexes… Rien de spécial. Mais son DDL montre que c’est une table mémoire :

Mémoire Remplie De Tables

Mémoire Remplie De Tables (« Le Petit DBA Illustré », 1889, édition « La Névrose »)


show create table base01.t_putAllThings;

CREATE TABLE `t_putAllThings` (
(...)

) ENGINE=MEMORY DEFAULT CHARSET=utf8

Ah aaaaah ! Intéressant. Manque-t-il de la mémoire ? Non.

C’est donc un problème de configuration (et de conception : nous y viendrons).

Il y a deux paramètres qui peuvent influencer le comportement d’une table en mémoire : « max_heap_table_size » (la taille maximum que la table peut occuper en mémoire) et « tmp_table_size » (la taille à partir de laquelle ladite table sera descendue sur disque en tant que table MyISAM temporaire).

Dans le cas où leur valeur est différente, le moteur se base sur la plus basse. Il faut donc prendre garde à bien changer les deux. Par défaut, selon le modèle choisi, la valeur se situe entre 16M et 64M.

La correction

Pour être exhaustif, voici comment les changer :

  • Dans le fichier de configuration (par défaut my.cnf mais ce peut être n’importe quel nom si votre distribution inclue le support du répertoire « my.cnf.d ») :

max_heap_table_size=128M
tmp_table_size=128M

Et redémarrage pour prise en compte.

  • En attendant, vous pouvez modifier ces paramètres

Dans MySQL :


set global tmp_table_size=134217728;

show global variables like 'tmp_table_size';

set global max_heap_table_size=134217728;

show global variables like 'max_heap_table_size';

Conclusion

Une première augmentation de ces deux paramètres a permis temporairement de faire passer le traitement. Mais la requête est mal codée et fait un produit cartésien. Conséquence : dès que le volume de données augmente, les données triées dans la table temporaire augmentent exponentiellement.

Au final, la balle est dans le camps des développeurs qui doivent optimiser leur code. Et mettre des indexes. Ils peuvent compter sur le soutien de leur collègues DBA qui, entre deux persiflages et un florilège de doctes leçons, les aideront de leur mieux car, au fond, tout au fond de ces hommes bourrus, il y a un cœur qui bat.

 

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 !

(1) MariaDB, pour être exact, mais aucune importance dans le cas qui nous intéresse