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

alf*_*ish 17 mysql linux query kill-process

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

pQd*_*pQd 23

查看percona 工具包中的pt-kill命令。

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

  • pt-kill 经过很好的测试,可以解决您的确切问题。找出命令行参数并让它运行大约需要 10 分钟。你还想要什么? (6认同)

Rol*_*DBA 14

如果您有 MySQL 5.1,其中 processlist 在 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
Run Code Online (Sandbox Code Playgroud)

您可以针对 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
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式进行 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
Run Code Online (Sandbox Code Playgroud)

这是另一个变体:

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
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您没有指定 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@***** ~]#
Run Code Online (Sandbox Code Playgroud)

在过去的 5 年里,我一直在做这项技术。事实上,我去年向 DBA StackExchange 提交了这个答案,它被接受了


Nil*_*ils 6

我在这里找到了以下代码:

2013 年 1 月 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
Run Code Online (Sandbox Code Playgroud)