我正在寻找一个经过良好测试的bash脚本(或替代解决方案)来这样做,以避免max_connection耗尽。我知道它正在解决症状,但确实需要这样的脚本作为短期解决方案。
我正在寻找一个经过良好测试的bash脚本(或替代解决方案)来这样做,以避免max_connection耗尽。我知道它正在解决症状,但确实需要这样的脚本作为短期解决方案。
Answers:
从percona工具箱中检出pt-kill命令。
和..不要开始监控系统- 穆宁,仙人掌与MySQL的更好的仙人掌模板,任何事情,所以你得到一些想法发生了什么事情。记录mysql慢查询也是一个好主意。
如果您的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
顺便说一句,由于我从information_schema.processlist显式读取为完全限定的表名,因此您没有指定myDB。
这是您应该看到的演示。对于此示例,我将回显所有时间> 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并被接受。
我在这里找到了以下代码片段:
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
如果您希望正常运行时间,我不会尝试bash解决方案!
如果您有权访问代码,则可以使用此处概述的方法实际设置SELECT语句的最大执行时间:
SELECT
MAX_EXECUTION_TIME = 1000 --in milliseconds
*
FROM table;
否则,在服务器上:
/programming/415905/how-to-set-a-maximum-execution-time-for-a-mysql-query
安装pt-kill:
$ wget percona.com/get/pt-kill
为您的流程列表创建快照:
$ mysql -u root -B -pmyreallyimportantpassword -e "show processlist;" > processlist.txt
在快照上测试pt-kill:
$ ./pt-kill --test-matching processlist.txt --busy-time 45 --kill-busy-commands 'Execute' --victims all --print
# 2019-02-25T17:34:37 KILL 45710302 (Execute 374 sec) SELECT\n\tCOUNT(DISTINCT(LP.sessionId))\nFROM lp_traffic LP\nINNER JOIN orders O ON O.orderId = LP.order
# 2019-02-25T17:34:37 KILL 45713515 (Execute 67 sec) SELECT \n\tCOUNT(DISTINCT(CASE WHEN T.response = 'SUCCESS' AND T.isVoid = 0 AND (T.txnType IN
确保匹配规则适合您的情况。以上这些将在45秒内杀死所有Execute语句。确定后,请修改并运行此命令以10秒的间隔执行该语句:
$ ./pt-kill -u root -p myreallyimportantpassword --busy-time 45 --kill-busy-commands 'Execute' --victims all --interval 10 --kill