MySQL 运行一段时间后(通常为 4-6 小时),一些较大、负载较强的查询会永久(直到重新启动)失败,并返回以下错误:
Can't create/write to file '#sql_75ed_0.MYD' (Errcode: 17)
谷歌搜索此错误会返回许多可能的原因,但我觉得可以通过两种简单的方法解决;
1)优化查询。(从长远来看,这是一个很好的解决方案。)
2) 以某种方式调整 MySQL 配置。(这是我想要做的)
针对这个问题,以下是我们当前在 my.cnf 中的非默认值:
query_cache_size = 8M
query_cache_limit = 8M
thread_cache_size = 4
max_connections = 90
table_cache = 4096
innodb_buffer_pool_size = 900M
tmp_table_size = 512M
max_heap_table_size = 256M
innodb_file_per_table
我倾向于相信,通过进一步调整这些变量,我们可能会注意到显著的性能提升,但这是一个有待后续提问的问题。
以下是开始失败的示例查询:
SELECT DISTINCT u.user_id, u.username, u.username_clean, u.user_colour, MAX(s.session_time) as online_time, MIN(s.session_viewonline) AS viewonline FROM (table_users u, table_zebra z) LEFT JOIN table_sessions s ON (s.session_user_id = z.zebra_id) WHERE z.user_id = 4 AND z.friend = 1 AND u.user_id = z.zebra_id GROUP BY z.zebra_id, u.user_id, u.username_clean, u.user_colour, u.username ORDER BY u.username_clean ASC
上述查询的 EXPLAIN 结果返回以下内容:
1, 'SIMPLE', 'z', 'ref', 'PRIMARY,zebra_id_friend', 'PRIMARY', '3', 'const', 18, 'Using where; Using temporary; Using filesort'
1, 'SIMPLE', 's', 'ref', 'session_user_id', 'session_user_id', '3', 'database_name.z.zebra_id', 402, ''
1, 'SIMPLE', 'u', 'eq_ref', 'PRIMARY', 'PRIMARY', '3', 'database_name.z.zebra_id', 1, ''
任何援助将不胜感激!
答案1
这很难懂,但我认为你可能(只是可能)有一堆像这样的死 SQL 临时表,最终 mysqld 尝试重用相同的文件名并失败,因为它有内部规则告诉它永远不要覆盖.MYD
.
我的建议是查看这些#sql_XXXX_X.MYD
文件所在的位置,关闭 mysqld,清除临时文件并重新启动它。
如果确实如此,优化查询似乎会有所帮助,前提是您可以让它不创建临时表,但除非您清除死文件,否则好处将是虚幻的。不过,优化查询以便将来不太可能获得死临时表是一个好主意。
答案2
MySQL 在某些情况下会创建临时文件来处理查询结果。一种常见的情况是,对文本或 blob 类型的列数据进行排序。其他情况包括,当允许的最大临时表大小已用尽时。
这些表的创建表明查询可能未完全优化,但在某些情况下无法避免。但是,您不应该收到错误(在我使用的一些生产环境中,每分钟可能会创建数十个这样的错误)。
通常文件是在 /tmp 中创建的。您可以查看该目录并查看它们的创建和销毁情况。如果 /tmp 或正在使用的任何目录对 mysql 用户不可写,则这可能是您的问题。
否则,请寻找更常见的问题,例如磁盘空间不足。