web-dev-qa-db-fra.com

Fichier de clé MySQL incorrect pour la table tmp lors de plusieurs jointures

Je ne viens pas souvent chercher de l'aide, mais je suis assez frustré par cela et j'espère que quelqu'un l'a déjà rencontré.

Chaque fois que j'essaie de récupérer des enregistrements d'une table à l'aide de plusieurs jointures, j'obtiens cette erreur:

#126 - Incorrect key file for table '/tmp/#sql_64d_0.MYI'; try to repair it

Cette requête produira donc l'erreur:

SELECT * FROM `core_username`
INNER JOIN `core_person` ON (`core_username`.`person_id` = `core_person`.`id`)
INNER JOIN `core_site` ON (`core_username`.`site_id` = `core_site`.`id`)
ORDER BY `core_username`.`name` ASC LIMIT 1

Mais celui-ci ne:

SELECT * FROM `core_username`
INNER JOIN `core_person` ON (`core_username`.`person_id` = `core_person`.`id`)
ORDER BY `core_username`.`name` ASC LIMIT 1

Et celui-ci non plus:

SELECT * FROM `core_username`
INNER JOIN `core_site` ON (`core_username`.`site_id` = `core_site`.`id`)
ORDER BY `core_username`.`name` ASC LIMIT 1

Qu'est-ce qui peut causer cela? Je ne sais pas vraiment comment réparer une table tmp mais je ne pense pas vraiment que ce soit le problème car c'est une nouvelle table tmp à chaque fois. La table des noms d'utilisateur est assez grande (233 718 enregistrements en ce moment) mais je doute que cela ait quelque chose à voir avec cela.

Toute aide serait très appréciée.

[~ # ~] mise à jour [~ # ~] : Après quelques tests supplémentaires, il semble que l'erreur ne se produit que lorsque j'essaie de commander les résultats. Autrement dit, cette requête me donnera ce que j'attends:

SELECT * FROM `core_username`
INNER JOIN `core_person` ON (`core_username`.`person_id` = `core_person`.`id`)
INNER JOIN `core_site` ON (`core_username`.`site_id` = `core_site`.`id`)
LIMIT 1

Mais si j'ajoute le:

ORDER BY `core_username`.`name` ASC

L'erreur est déclenchée. Cela se produit uniquement sur le serveur Web spécifique que j'utilise actuellement. Si je télécharge la base de données et essaie la même chose sur mon hôte local ainsi que sur d'autres serveurs, cela fonctionne bien. La version MySQL est 5.0.77.

Sachant cela, je suis assez confiant que ce qui se passe, c'est que la table tmp en cours de création est beaucoup trop grande et MySQL s'étouffe comme décrit dans ce billet de blog . Je ne sais toujours pas quelle serait la solution, cependant ...

57
Paolo Bergantino

Parfois, lorsque cette erreur se produit avec les tables temporaires:

#126 - Incorrect key file for table '/tmp/#sql_64d_0.MYI'; try to repair it

Cela peut être dû au fait que le /tmp Le dossier manque d'espace. Sur certaines installations Linux, /tmp est dans sa propre partition et n'a pas beaucoup d'espace - les grandes requêtes MySQL le rempliront.

Vous pouvez utiliser df -h pour vérifier si \tmp est dans sa propre partition, et combien d'espace lui est alloué.

S'il se trouve dans sa propre partition et manque d'espace, vous pouvez soit:

(a) modifier/tmp pour que sa partition ait plus d'espace (soit en la réallouant, soit en la déplaçant vers la partition principale - par exemple voir ici )
(b) changer la configuration MySql pour qu'elle utilise un dossier temp différent sur une partition différente, par ex. /var/tmp

102
codeulike

Vérifiez votre espace disponible MySQL tmpdir (/ tmp dans votre cas) pendant l'exécution des requêtes car il peut consommer des centaines de Mo lorsque vous travaillez avec de grandes tables. Quelque chose comme ça a fonctionné pour moi:

$ while true; do df -h /tmp; sleep .5; done
20
Francesc Rosàs

lance ça

REPAIR TABLE `core_username`,`core_site`,`core_person`;

ou faites ceci:

select * from (
 SELECT * FROM `core_username`
 INNER JOIN `core_person` ON (`core_username`.`person_id` = `core_person`.`id`)
 INNER JOIN `core_site` ON (`core_username`.`site_id` = `core_site`.`id`)
 LIMIT 1)
ORDER BY `name` ASC
6
Pentium10

Vous trouverez peut-être utile d'exécuter "ANALYZE TABLE".

Nous avons eu ce problème soudainement sur une grande table (~ 100 millions de lignes) et MySQL a essayé d'utiliser/tmp pour écrire une table temporaire de plus de 1 Go, ce qui a échoué car/tmp était limité à ~ 600 millions.

Il s'est avéré que les statistiques de la table InnoDB étaient plutôt périmées. Après avoir exécuté "ANALYZE TABLE ...", les statistiques ont été mises à jour et le problème a été résolu. Avec des statistiques plus précises, MySQL a pu optimiser la requête correctement et le gros fichier tmp n'était plus nécessaire.

Nous exécutons maintenant "mysqlcheck -Aa" périodiquement pour garder toutes les statistiques de table à jour.

4
Roger Lucas

J'ai eu ce problème avec une requête sur une table qui avait 500K + enregistrements. Cela me donnait le même type d'erreur exact, pointant vers un fichier .MYI dans le répertoire/tmp qui était rarement là lors de la vérification. J'avais déjà augmenté la taille des fichiers tas et temp dans le fichier /etc/my.cnf.

Le problème avec la requête était qu'elle contenait en effet une clause ORDER à la fin, en omettant de faire fonctionner la requête sans erreur. Il avait également une LIMITE. J'essayais de regarder les 5 enregistrements les plus récents du tableau. Avec la clause ORDER incluse, elle s'est étouffée et a donné l'erreur.

Ce qui se passait, c'était que mysqld créait une table temporaire interne avec TOUS les enregistrements de la table géante pour appliquer l'ORDRE.

La façon dont je me suis débrouillé est d'appliquer une condition WHERE supplémentaire, limitant les enregistrements de la table géante à un ensemble plus petit. J'avais commodément un champ datetime pour faire le filtrage.

J'espère que cela aide quelqu'un.

3
ClickWhisperer

Sous Unix, MySQL utilise la valeur de la variable d'environnement TMPDIR comme nom de chemin du répertoire dans lequel stocker les fichiers temporaires. Si TMPDIR n'est pas défini, MySQL utilise la valeur par défaut du système, qui est généralement/tmp,/var/tmp ou/usr/tmp.

Sous Windows, Netware et OS2, MySQL vérifie dans l'ordre les valeurs des variables d'environnement TMPDIR, TEMP et TMP. Pour le premier trouvé, MySQL l'utilise et ne vérifie pas ceux qui restent. Si aucun TMPDIR, TEMP ou TMP n'est défini, MySQL utilise la valeur par défaut du système Windows, qui est généralement C:\windows\temp.

Si le système de fichiers contenant votre répertoire de fichiers temporaires est trop petit, vous pouvez utiliser l'option --tmpdir pour mysqld pour spécifier un répertoire dans un système de fichiers où vous avez suffisamment d'espace.

Dans MySQL 5.0, l'option --tmpdir peut être définie sur une liste de plusieurs chemins qui sont utilisés de manière circulaire. Les chemins doivent être séparés par des deux points (":") sous Unix et des points-virgules (";") sous Windows, NetWare et OS/2.

2
Jaydeep Dave

J'éprouve le même problème.

Voici ma solution: 1. N'utilisez pas "select *". Sélectionnez simplement le champ dont vous avez besoin. 2. Divisez la requête. Si le champ que vous sélectionnez est trop, le fractionnement en une requête peut être un résultat. Vous pouvez "array_merge ()" le résultat plus tard si vous souhaitez que la variable qui contient le résultat ne soit pas modifiée.

Dans mon cas, j'ai divisé la requête en 5 requêtes, puis je l'ai fusionnée en utilisant PHP.

Le problème réside sur le serveur mysql. C'est juste une chose que le développeur d'applications (comme nous) n'a pas de privilège.

1
Ahmad

J'ai eu un problème similaire. Dans mon propre cas, le problème s'est produit en raison d'un propriétaire/d'une autorisation incorrect. Je viens de changer le propriétaire de mon répertoire de données en utilisateur mysql et cela a résolu le problème.

0
Lateef
0
DarckBlezzer