如何在 N 秒后自动终止慢速 MySQL 查询?

如何在 N 秒后自动终止慢速 MySQL 查询?

我正在寻找一个经过充分测试的 bash 脚本(或替代解决方案)来执行此操作,以避免 max_connection 耗尽。我知道这是在对抗症状,但确实需要这样的脚本作为短期解决方案。

答案1

查看pt-kill命令来自percona 工具包

并且..开始监控你的系统 -穆宁仙人掌适用于 mysql 的更好的 cacti 模板,任何事情,这样你就会知道发生了什么。记录 mysql 慢查询也是一个好主意。

答案2

如果您拥有 MySQL 5.1,其中进程列表位于 INFORMATION_SCHEMA 中,则可以执行以下操作从 mysql 客户端内部批量生成 KILL QUERY 命令,用于运行时间超过 20 分钟(1200 秒)的查询:

SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery
FROM information_schema.processlist WHERE user<>'system user'
AND time >= 1200\G

您可以针对 INFO 字段执行 WHERE 子句来查找特定查询,针对 TIME 字段查找长时间运行的查询,或针对特定数据库执行 DB 字段。

如果你是 root@localhost,你应该有完全权限来运行以下命令

SECONDS_TOO_LONG=1200
KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword

您可以按如下方式执行 crontab 任务:

SECONDS_TOO_LONG=1200
QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
    KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
    mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword
fi

这是另一种变化:

SECONDS_TOO_LONG=1200
QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
    KILLPROC_SQLSTMT="SELECT CONCAT('KILL QUERY ',id,';') KillQuery FROM information_schema.processlist WHERE user<>'system user' AND time >= ${SECONDS_TOO_LONG}"
    mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" > /tmp/kill_log_queries.sql
    mysql -uroot -ppassword < /tmp/kill_log_queries.sql
fi

顺便说一句,您不必指定 myDB,因为我明确从 information_schema.processlist 读取作为完全合格的表名。

以下是您应该看到的内容的演示。在这个例子中,我将回显所有时间 > 20000 秒的进程的 KILL 命令:

[root@***** ~]# mysql `lwdba_connect` -ANe"SELECT GROUP_CONCAT('KILL ',id,'; ' SEPARATOR ' ') FROM information_schema.processlist WHERE time > 25000 AND user<>'system user';"
+----------------------------------------------------+
| KILL 180186;  KILL 180141;  KILL 176419;  KILL 3;  |
+----------------------------------------------------+
[root@***** ~]#

我已经使用这项技术五年了。事实上,我去年向 DBA StackExchange 提交了这个答案,并被接受了

答案3

我发现以下代码片段这里

更新2013-01-14:有匿名人士暗示,这可能很危险,并且可能会终止复制进程。因此,请自行承担风险:

mysql -e 'show processlist\G' |\
egrep -b5 'Time: [0-9]{2,}' |\
grep 'Id:' |\
cut -d':' -f2 |\
sed 's/^ //' |\
while read id
do
  mysql -e "kill $id;"
done

答案4

MySQL 5.7 以上版本可以使用最大执行时间变量来为所有“SELECT”读取查询自动完成此操作。

相关内容