N秒後に遅いMySQLクエリを自動的に強制終了する方法は?


16

max_connectionが使い果たされるのを避けるために、十分にテストされたbashスクリプト(または代替ソリューション)を探しています。私はそれが症状と戦っていることを知っていますが、本当に短期的な解決策としてそのようなスクリプトが必要です。


実行しているMySQLのバージョン???
-RolandoMySQLDBA

mysqlバージョンは5.5
alfish

回答:


21

perconaツールキットからpt-killコマンドを確認してください。

そして...あなたのシステムの監視を開始します- のmuninサボテンMySQLのためのより良いサボテンのテンプレート、何でもあなたが上で何が起こっているのか、いくつかのアイデアを得るようにします。mysqlの遅いクエリを記録することも良い考えです。


提案に感謝しますが、実際には「1回限りの」スクリプトを探してください。
アルフィッシュ

5
pt-killは非常によくテストされ、正確な問題を解決します。コマンドラインパラメータを把握して実行するには、10分ほどかかります。さらに何が欲しいですか?
アーロンブラウン

12

プロセスリストがINFORMATION_SCHEMAにあるMySQL 5.1がある場合、これを実行して、20分(1200秒)より長いクエリを実行するためにmysqlクライアント内からKILL QUERYコマンドを一括で生成できます。

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@***** ~]#

私はこの5年間、この手法を行ってきました。実際、私は昨年、この回答をDBA StackExchangeに提出し、受け入れられました


ローランド、これらを明確にしてください:このコマンドは永続的ですか、または頻繁に実行する必要がありますか?mysqlユーザーが「root」で、データベース名がmyDBであると仮定して、コマンドで何を置き換える必要がありますか?ありがとう
-alfish

回答を更新しました。
RolandoMySQLDBA

感謝しますが、最後のレシピをbashスクリプトに変えた後、1行目でERROR 1064(42000)になります。SQL構文にエラーがあります。MySQLサーバーのバージョンに対応するマニュアルで、1行目付近の ''
-alfish

どのSQLコマンドがそのエラーを生成しましたか???
-RolandoMySQLDBA

ローランドSFはサンドボックスではありません。解決策として何かを提案する前にテストすることをお勧めします。さらに、すべての接続が飽和状態になった場合、mysqlがどのようにプロシージャを実行するのでしょうか?
アルフィッシュ

6

ここで次のコードを抜粋しました

更新 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

上記のスニペットの時定数は何ですか?
アルフィッシュ

@alfish私は著者ではありません-しかし、これは少なくとも2桁のすべての時間値に一致する正規表現であると言えます。したがって、ここでの仮定は、10は長すぎるということです。
ニルス

1

MySQL 5.7以降では、max_execution_time変数を使用して、すべての「SELECT」読み取りクエリに対してこれを自動的に実行できます。


0

稼働時間が好きなら、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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.