60

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

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

#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

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

知道了这一点,我相当有信心正在发生的事情是正在创建的 tmp 表太大,并且 MySQL 阻塞,如本文所述。我仍然不确定解决方案是什么,虽然......

4

11 回答 11

106

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

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

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

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

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

(a) 修改 /tmp 使其分区有更多空间(通过重新分配或将其移动到主分区 - 例如,请参见此处
(b) 更改 MySql 配置,以便它在不同分区上使用不同的临时文件夹,例如/var/tmp

于 2010-09-15T10:34:03.710 回答
21

在运行查询时检查您的 MySQL tmpdir 可用空间(在您的情况下为 /tmp),因为在处理大表时它可能会占用数百 MB。像这样的东西对我有用:

$ while true; do df -h /tmp; sleep .5; done
于 2010-03-04T11:01:40.407 回答
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
于 2010-01-28T13:36:54.337 回答
4

您可能会发现运行“分析表”会有所帮助。

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

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

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

于 2011-09-22T07:57:29.080 回答
3

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

查询的问题是它确实在末尾包含一个 ORDER 子句,省略它使查询工作没有错误。它也有一个限制。我试图查看表中最近的 5 条记录。包含 ORDER 子句时,它会窒息并给出错误。

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

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

我希望这对某人有所帮助。

于 2013-12-12T00:29:39.573 回答
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 上用分号字符 (“;”) 分隔。

于 2012-03-27T18:22:23.713 回答
1

我遇到同样的问题。

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

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

问题出在mysql服务器上。这只是应用程序开发人员(例如我们)没有特权的事情。

于 2012-08-09T05:33:27.903 回答
0

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

于 2014-09-02T13:27:49.357 回答
0

只增加文件tmp,因为mysql里面没有空间,用于查询...

mount -o remount,size=[NEW MAX SIZE HERE] tmpfs /tmp

链接参考:

一般错误:126 表'/tmp/#sql_254c_0.MYI'的密钥文件不正确;尝试修复它

[错误] /usr/sbin/mysqld:表'/mysqltmp/#sql_ca1a_0.MYI'的密钥文件不正确;尝试修复它

如何增加 /tmp 分区大小

于 2016-07-08T23:18:05.107 回答
-1

3 个表之一的索引键可能不好,请尝试对所有 3 个表运行修复命令。

于 2010-01-28T13:31:25.303 回答
-1

使用 EXPLAIN 关键字可能有助于找出如何最好地优化此查询。本质上,您需要做的是尽快获得尽可能小的结果集。如果您在 core_username 中的每一行都有一个结果集直到最后,那么当您订购它时,您将冒着......这个的风险。

如果您可以单独对 core_username 进行排序而不会出现问题,您可能希望将 min() 行作为子查询。

于 2010-01-29T17:42:42.033 回答