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

是否有可能在MySQL中超时查询?

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

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

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

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

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

root用户应该能够运行本地mysql工具而无需身份validation,否则您将需要在命令行上提供凭据。

我只是将下面的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 

从MySQL 5.1开始,您可以创build一个存储过程来查询information_schmea.PROCESSLIST表,查找与“长时间运行”条件相匹配的所有查询,然后遍历游标以杀死它们。 然后设置该过程在事件调度程序中定期执行。

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

我以为已经有一段时间了,但据此,

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

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

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

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

这篇文章详细介绍了如何使用innodb_lock_wait_timeout在服务器上设置超时。

这是一种以编程方式执行的方法 ,假设您使用的是JDBC。

我不认为上面的egrep会find“2000”。
为什么不尝试只selectID,并避免所有的豪华贝壳的东西:

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

这是我的脚本:

 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 

由于MySQL 5.7.8有max_execution_time选项,它定义了SELECT语句的执行超时。

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

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

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 。 它不适用于stored procedures中的SELECT语句。 在存储的程序中使用SELECT语句中的MAX_EXECUTION_TIME提示将被忽略。

要杀死基于他们的thread_id查询尝试查询并手动杀死他们,

SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND ='查询'AND TIME> 10;

另一种交互方式是使用查询将值输出到文件,

 SELECT CONCAT('KILL ',ID,';') FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'new' AND COMMAND = 'Query' AND TIME > 10 INTO OUTFILE '/tmp/thread_kill.txt'; 

然后杀死文件中的线程使用,

  \. /tmp/thread_kill.txt 

另一种方法是寻找像MONyog,MySQL Enterprise Monitor,Percona工具包这样的监视工具,在这里你可以让工具查找更长/更慢的查询,locking查询并杀死它们。 有了MONyog ,增加的好处是不仅可以杀死缓慢的查询,还可以通过电子邮件通知用户哪些查询占用了资源并使服务器变慢。