具有大量记录的MySQL查询被终止

时间:2013-08-07 13:34:38

标签: mysql command-line-interface

我从我的shell运行以下查询:

    mysql -h my-host.net -u myuser -p -e "SELECT component_id, parent_component_id FROM myschema.components comp INNER JOIN my_second_schema.component_parents related_comp ON comp.id = related_comp.component_id ORDER BY component_id;" > /tmp/IT_component_parents.txt

查询运行时间很长,然后被杀死。

但是,如果我添加LIMIT 1000,则查询将一直运行到结尾,输出将写入文件中。

我进一步调查并发现(使用COUNT(*)),将返回的记录总数为239553163。

有关我的服务器的一些信息在这里:

MySQL 5.5.27

    +----------------------------+----------+
    | Variable_name              | Value    |
    +----------------------------+----------+
    | connect_timeout            | 10       |
    | delayed_insert_timeout     | 300      |
    | innodb_lock_wait_timeout   | 50       |
    | innodb_rollback_on_timeout | OFF      |
    | interactive_timeout        | 28800    |
    | lock_wait_timeout          | 31536000 |
    | net_read_timeout           | 30       |
    | net_write_timeout          | 60       |
    | slave_net_timeout          | 3600     |
    | wait_timeout               | 28800    |
    +----------------------------+----------+

这是我监控的查询的状态:

    copying to tmp table on disk
    sorting results
    sending data
    writing to net
    sending data
    writing to net
    sending data
    writing to net
    sending data ...
    KILLED

任何猜测这里有什么问题?

5 个答案:

答案 0 :(得分:17)

mysql客户端可能内存不足。

使用--quick选项不将结果缓冲在内存中。

答案 1 :(得分:1)

错误的是您要返回239 553 163行数据!不要惊讶它需要花费大量时间来处理。实际上,最长的部分可能就是将结果集发送回客户端。

重新生成结果集(你真的需要所有这些行吗?)。或者尝试以较小批量输出数据:

mysql -h my-host.net -u myuser -p -e "SELECT ... LIMIT 10000, 0" >> dump.txt
mysql -h my-host.net -u myuser -p -e "SELECT ... LIMIT 10000, 10000" >> dump.txt

答案 2 :(得分:1)

假设您说的是长时间的8小时,28800的值wait_timeout会导致连接在28,800秒(即8小时)内没有进一步活动。如果无法优化语句在8小时内运行,则应增加此值。

有关wait_timeout变量的详细信息,请参阅this page

interactive_timeout变量用于交互式客户端连接,因此如果您从交互式会话中运行长查询,则需要查看该查询。

答案 3 :(得分:0)

如果要转储大量数据,可能需要使用OUTFILE机制。那个或mysql_dump会更有效率(OUTFILE得益于不锁定表格。)

答案 4 :(得分:0)

您在评论中说您的MySQL实例在RDS上。这意味着您无法从同一主机运行查询,因为您无法登录RDS主机。我猜你可能正在通过本地网络在WAN上进行此查询。

由于网络速度慢,您很可能遇到麻烦。您的流程状态经常显示“写入网络”让我觉得这是您的瓶颈。

您的瓶颈也可能是排序。您的排序是写入临时表,这可能需要很长时间才能得到大的结果集。你能跳过ORDER BY吗?

即便如此,我也不希望查询被杀死,即使它运行3100秒或更长时间。我想知道你的DBA是否有一些定期的工作可以杀死长时间运行的查询,例如pt-kill。问你的DBA。

要减少网络传输时间,您可以尝试使用压缩协议。您可以使用--compress-C标志到mysql客户端(参见https://dev.mysql.com/doc/refman/5.7/en/mysql-command-options.html#option_mysql_compress

在慢速网络上,压缩可以提供帮助。例如,请阅读此处的一些比较:https://www.percona.com/blog/2007/12/20/large-result-sets-vs-compression-protocol/

另一种方法是从与RDS实例在同一AZ中运行的EC2 spot实例运行查询。这两个实例之间的网络速度会快得多,因此不会延迟数据传输。将查询输出保存到EC2 spot实例上的文件中。

将查询结果保存在您的EC2实例后,您可以使用scp或其他内容将其下载到本地计算机,这应该更能容忍慢速网络。