在进行多个连接时,MySQL不正确的tmp表密钥文件

时间:2010-01-18 23:55:02

标签: mysql sql mysql-error-126

我不经常来这里寻求帮助,但我对此感到非常沮丧,我希望以前有人遇到过它。

每当我尝试使用多个连接从表中获取记录时,我都会收到此错误:

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

因此,此查询将产生错误:

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

但是这个不会:

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

这一个也不会:

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

可能导致这种情况的原因是什么?我真的不知道如何修复tmp表,但我不认为这是问题,因为它每次都是一个新的tmp表。用户名表相当大(现在有233,718条记录),但我怀疑它与它有什么关系。

非常感谢任何帮助。

更新:经过一些进一步测试后,似乎只有在我尝试订购结果时才会出现错误。也就是说,这个查询会给我我的期望:

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 `core_username`.`name` ASC

触发错误。这只发生在我目前使用的特定网络服务器上。如果我下载数据库并在我的localhost以及其他服务器上尝试相同的操作,它运行正常。 MySQL版本是5.0.77。

知道这一点我相信发生的事情是创建的tmp表太大而MySQL扼杀了as described in this blog post。我仍然不确定解决方案是什么,但是......

11 个答案:

答案 0 :(得分:101)

有时当临时表发生此错误时:

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

可能是因为/tmp文件夹空间不足。在某些Linux安装中,/tmp位于其自己的分区中并且没有太多空间 - 大的MySQL查询将填满它。

您可以使用df -h检查\tmp是否在自己的分区中,以及分配了多少空间。

如果它在自己的分区中且空间不足,您可以:

(a)修改/ tmp,使其分区有更多空间(通过重新分配或移动到主分区 - 例如see here
 (b)更改MySql配置,以便它在不同的分区上使用different temp folder,例如/var/tmp

答案 1 :(得分:20)

在运行查询时检查你的MySQL tmpdir可用空间(在你的情况下为/ tmp),因为在使用大表时可能会吃掉数百MB。这样的事情对我有用:

$ while true; do df -h /tmp; sleep .5; done

答案 2 :(得分:6)

运行此

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

或者这样做:

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

答案 3 :(得分:4)

您可能会发现正在运行“ANALYZE TABLE”帮助。

我们遇到这个问题突然出现在一个大表(~100M行)上,MySQL试图使用/ tmp写一个超过1GB的临时表,由于/ tmp被限制在~600M左右而失败。

事实证明,InnoDB表的统计数据相当陈旧。运行“ANALYZE TABLE ...”后,统计信息已更新,问题已清除。通过更准确的统计数据,MySQL能够正确优化查询,并且不再需要大型tmp文件。

我们现在定期运行“mysqlcheck -Aa”以保持所有表统计信息的新鲜度。

答案 4 :(得分:3)

我在一个有500K +记录的表上查询时遇到了这个问题。 它给了我相同的确切类型的错误,指向/ tmp目录中的.MYI文件,该文件很少在检查时出现。我已经在/etc/my.cnf文件中增加了堆和临时文件大小。

查询的问题是它确实在最后包含了一个ORDER子句,省略它使查询正常工作而没有错误。它也有一个限制。我试图查看表中最近的5条记录。包含ORDER子句后,它会被阻塞并给出错误。

正在发生的事情是mysqld正在创建一个内部临时表,其中包含来自巨型表的所有记录以应用ORDER。

我解决这个问题的方法是应用一个额外的WHERE条件,将巨型表中的记录限制为一些较小的集合。我方便地有一个日期时间字段来进行过滤。

我希望能有所帮助。

答案 5 :(得分:2)

在Unix上,MySQL使用TMPDIR环境变量的值作为存储临时文件的目录的路径名。如果未设置TMPDIR,MySQL将使用系统默认值,通常为/ tmp,/ var / tmp或/ usr / tmp。

在Windows,Netware和OS2上,MySQL按顺序检查TMPDIR,TEMP和TMP环境变量的值。对于第一个发现设置,MySQL使用它并不检查剩余的。如果没有设置TMPDIR,TEMP或TMP,则MySQL使用Windows系统默认值,通常为C:\ windows \ temp。

如果包含临时文件目录的文件系统太小,可以使用mysqld的--tmpdir选项指定文件系统中有足够空间的目录

在MySQL 5.0中, - tmpdir选项可以设置为以循环方式使用的多个路径的列表。路径应该用Unix上的冒号字符(“:”)和Windows,NetWare和OS / 2上的分号字符(“;”)分隔。

答案 6 :(得分:1)

我遇到了同样的问题。

这是我的解决方案: 1.不要使用“选择*”。只需选择您需要的字段即可。 2.拆分查询。如果您选择的字段太多,则可能会将其拆分为某个查询。如果希望包含结果的变量未更改,则可以稍后“array_merge()”结果。

就我而言,我将查询拆分为5个查询,然后使用PHP将数组合并。

问题在于mysql服务器。应用程序开发人员(比如我们)没有普遍性,这只是一件事。

答案 7 :(得分:0)

我有类似的问题。在我自己的情况下,问题是由于不正确的所有者/权限。我只需要将我的数据目录中的所有者更改为mysql用户,这就解决了这个问题。

答案 8 :(得分:0)

答案 9 :(得分:-1)

3个表中某个表的索引键可能不好,请尝试在所有3个表上运行修复命令。

答案 10 :(得分:-1)

使用EXPLAIN关键字有助于了解如何最佳地优化此查询。基本上,您需要做的是尽可能快地将结果集尽可能小。如果你有一个core_username中每一行的结果集,直到最后,当你订购它时,你冒着......这个风险。

如果你可以单独对core_username进行排序而没有问题,你可能希望将min()行作为子查询。