如果需要太长时间,如何停止 MySQL 查询?
Posted
技术标签:
【中文标题】如果需要太长时间,如何停止 MySQL 查询?【英文标题】:How can I stop a MySQL query if it takes too long? 【发布时间】:2011-01-09 08:58:56 【问题描述】:是否可以在 mysql 中使查询超时?
也就是说,如果任何查询超过了我指定的时间,它就会被 MySQL 杀死,它会返回错误而不是等待永恒。
【问题讨论】:
帮助我们回答这个问题 - 您是在代码内部还是外部尝试这样做?如果您想要特定语言的答案,选择哪一种? 我不知道任何ANSI SQL,但我知道如何在一些消费应用程序中做到这一点——它们是如何连接的?每个连接都有join-limit
语法,您可以在应用程序中执行很多操作。
对不起,我很愚蠢,我忘了具体说明。我不想在我的代码中执行此操作,我想知道,是否可以在 mysql self 中执行此查询超时,例如:查询运行 120 秒,限制为 120,因此 mysql 将终止此查询并返回一些错误或者其他的东西。我遇到了令人讨厌的 3rd 方代码问题,我无权编辑它。我需要在 mysql 中终止该查询,而不是在代码中。
这工作:serverfault.com/a/402076/280625
【参考方案1】:
MySQL 论坛有一些关于此的主题。
This post 详细介绍了如何使用 innodb_lock_wait_timeout 在服务器上设置超时。
Here's a way to do it programmatically,假设您使用的是 JDBC。
【讨论】:
【参考方案2】:从 MySQL 5.1 开始,您可以创建一个存储过程来查询 information_schmea.PROCESSLIST 表中所有符合“长时间运行”条件的查询,然后遍历游标以终止它们。然后设置该过程以在事件调度程序中重复执行。
见:http://forge.mysql.com/tools/tool.php?id=106
【讨论】:
可以为 mysql 5.0 设置类似的东西还是 5.1 特定的? 死链接。存档:web.archive.org/web/20080323063602/http://forge.mysql.com/tools/…【参考方案3】:我刚刚将以下 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
【讨论】:
【参考方案4】:这是我的脚本:
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
【讨论】:
【参考方案5】:我认为上面的 egrep 不会找到“2000”。 为什么不尝试只选择 id 并避免所有那些豪华的 shell 东西:
mysql -e 'select id from information_schema.processlist where info is not null and time > 30;'
【讨论】:
【参考方案6】:在 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 工具,否则您需要在命令行上提供凭据。
【讨论】:
如今,该代码的更新/维护版本位于github.com/dailymotion/mysql-genocide【参考方案7】:我以为它已经存在了一段时间,但根据this,
MySQL 5.7.4 引入了为***只读 SELECT 语句设置服务器端执行时间限制的功能,以毫秒为单位。
SELECT
MAX_STATEMENT_TIME = 1000 --in milliseconds
*
FROM table;
请注意,这只适用于只读 SELECT 语句。
【讨论】:
NB:在 v 5.7.8 中重命名为 MAX_EXECUTION_TIME【参考方案8】:从 MySQL 5.7.8 开始,max_execution_time 选项定义了 SELECT 语句的执行超时。
【讨论】:
【参考方案9】:我认为这个老问题需要更新的答案。
您可以为所有只读SELECT
查询设置GLOBAL
超时,如下所示:
SET GLOBAL MAX_EXECUTION_TIME=1000;
指定的时间以毫秒为单位。
如果您只希望特定查询的超时,您可以像这样将其设置为内联:
SELECT /*+ MAX_EXECUTION_TIME(1000) */ my_column FROM my_table WHERE ...
MySQL 返回一个错误而不是等待永恒。
请注意,此方法仅适用于只读SELECT
s。如果确定SELECT
语句不是只读的,则取消为其设置的任何计时器并向用户报告以下 NOTE 消息:
Note 1908 Select is not a read only statement, disabling timer
对于带有子查询的语句,它只限制顶部的SELECT
。它不适用于存储程序中的SELECT
语句。在存储程序中的 SELECT
语句中使用 MAX_EXECUTION_TIME
提示将被忽略。
【讨论】:
这是在 Windows 上运行的 MySql 5.7.21 中工作的那个。以上是关于如果需要太长时间,如何停止 MySQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章
ORDER BY RAND()函数在mysql中执行需要很长时间[重复]