如果需要太长时间,我如何停止MySQL查询?

时间:2010-01-26 01:52:46

标签: mysql timeout

是否可以在MySQL中超时查询?

也就是说,如果任何查询超过我指定的时间,它将被MySQL杀死,它将返回错误而不是等待永恒。

9 个答案:

答案 0 :(得分:10)

CPAN上有一个很好的Perl脚本可以做到这一点: http://search.cpan.org/~rsoliv/mysql-genocide-0.03/mysql-genocide

只需要安排它使用适当的参数运行。创建一个CRONtab文件 /etc/cron.d/mysql_query_timeout 以安排它每分钟运行一次:

* * * * * root /path/to/mysql-genocide -t 7200 -s -K

其中7200是允许的最长执行时间(以秒为单位)。 -s开关过滤掉除SELECT查询之外的所有内容。 -K开关指示脚本终止匹配的进程。

root用户应该能够在没有身份验证的情况下运行本地mysql工具,否则您将需要在命令行上提供凭据。

答案 1 :(得分:9)

我只是将以下bash脚本设置为cron作业,以使用MySQL 5.0实现此目的(杀死任何执行超过30秒的查询)。如果它对任何人都有用,请在这里分享(如果我的bash脚本风格效率低或者很糟糕,那么这不是我的主要开发语言):

#!/bin/bash
linecount=0
processes=$(echo "show processlist" | mysql -uroot -ppassword)
oldIfs=$IFS
IFS='
'
echo "Checking for slow MySQL queries..."
for line in $processes
do
    if [ "$linecount" -gt 0 ]
        then
            pid=$(echo "$line" | cut -f1)
            length=$(echo "$line" | cut -f6)
            query=$(echo "$line" | cut -f8)
            #Id User    Host    db  Command Time    State   Info
            if [ "$length" -gt 30 ]
                then
                    #echo "$pid = $length"
                    echo "WARNING:  Killing query with pid=$pid with total execution time of $length seconds! (query=$query)"
                    killoutput=$(echo "kill query $pid" | mysql -uroot -ppassword)
                    echo "Result of killing $pid:  $killoutput"
            fi
    fi
    linecount=`expr $linecount + 1`
done
IFS=$oldIfs

答案 2 :(得分:8)

从MySQL 5.1开始,您可以创建一个存储过程来查询information_schmea.PROCESSLIST表,查找符合“长时间运行”条件的所有查询,然后遍历游标以终止它们。然后设置该过程以在事件调度程序中重复执行。

请参阅:http://forge.mysql.com/tools/tool.php?id=106

答案 3 :(得分:8)

我认为它已经存在了一段时间,但根据this

  

MySQL 5.7.4引入了为顶级只读SELECT语句设置服务器端执行时间限制的能力,以毫秒为单位。

SELECT 
MAX_STATEMENT_TIME = 1000 --in milliseconds
* 
FROM table;

请注意,这仅适用于只读SELECT语句。

答案 4 :(得分:7)

MySQL论坛有一些关于此的线索。

This post详细说明了如何使用innodb_lock_wait_timeout在服务器上设置超时。

Here's a way to do it programmatically,假设您正在使用JDBC。

答案 5 :(得分:3)

我不认为上面的egrep会找到" 2000" 为什么不尝试只选择id,并避免所有那些豪华的shell:

mysql -e 'select id from information_schema.processlist where info is not null and time > 30;'

答案 6 :(得分:3)

我认为这个老问题需要更新答案。

您可以为所有只读GLOBAL查询设置SELECT超时:

SET GLOBAL MAX_EXECUTION_TIME=1000;

指定的时间以毫秒为单位。

如果您只希望特定查询的超时,可以将其设置为内联,如下所示:

SELECT /*+ MAX_EXECUTION_TIME(1000) */ my_column FROM my_table WHERE ...

MySQL返回错误而不是等待永恒。

请注意,此方法仅适用于只读SELECT。如果确定SELECT语句不是只读语句,则取消为其设置的任何计时器,并向用户报告以下NOTE消息:

Note 1908 Select is not a read only statement, disabling timer

对于包含子查询的语句,它仅限制顶部SELECT。它不适用于存储程序中的SELECT语句。使用存储程序中MAX_EXECUTION_TIME语句中的SELECT提示将被忽略。

答案 7 :(得分:2)

这是我的剧本:

mysql -e 'show processlist\G' |\
egrep -b5 'Time: [6-9]{3,10}' |\
grep 'Id:' |\
cut -d':' -f2 |\
grep -v '155' |\ ## Binary Log PID
sed 's/^ //' |\
while read id
do
    mysql -e "kill $id;"
done

答案 8 :(得分:2)

自MySQL 5.7.8起,有max_execution_time选项定义SELECT语句的执行超时。