我正在寻找一个经过充分测试的 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”读取查询自动完成此操作。