ちょっと厨二っぽいSEのブログ

プログラミングとかのシステム備忘録など

【mysql】プロセスを条件検索で取得する方法【sleep】

DB負荷が高くなると、処理に長時間かかっているクエリが複数出てきてフリーズに近い状態になります。
以前以下の記事のような事象がおき、特定クエリの大量kill が必要になりました。
ryokwkm2.hatenadiary.jp


実行中のプロセスは以下のコマンドを使用して調べることができます

mysql> show processlist;

もしくはmysqlにログインせずに以下のコマンドでも可能です。
mysqladmin processlist

使用例(パスワードが設定されている場合)
mysqladmin processlist -u ユーザー名 -p

実行してみると以下のように結果が表示されました。

+----------+-------+-----------------------+-------------------+-------------+----------+-----------------------------------------------------------------------+------------------+
| Id       | User  | Host                  | db                | Command     | Time     | state                                                                 | info             |
+----------+-------+-----------------------+-------------------+-------------+----------+-----------------------------------------------------------------------+------------------+
| 1        | repl  | 192.168.0.142:47616   |                   | Binlog Dump | 18174357 | Master has sent all binlog to slave; waiting for binlog to be updated |                  |
| 43401230 | mysql | 183.79.135.206:43180  | DB名              | sleep       | 190      |                                                                       |                  |
| 43401247 | mysql | 183.79.135.206:43200  | DB名              | sleep       | 40       |                                                                       |                  |
| 43401313 | mysql | 183.79.135.206:43267  | DB名              | sleep       | 45       |                                                                       |                  |
| 43401694 | mysql | 183.79.135.206:43781  | DB名              | sleep       | 71       |                                                                       |                  |
| 43401820 | mysql | 183.79.135.206:43972  | DB名              | sleep       | 153      |                                                                       |                  |
| 43401853 | mysql | 183.79.135.206:44018  | DB名              | sleep       | 649      |                                                                       |                  |
| 43401945 | mysql | 183.79.135.206:44121  | DB名              | sleep       | 732      |                                                                       |                  |
| 43401958 | mysql | 183.79.135.206:44141  | DB名              | sleep       | 43       |                                                                       |                  |
| 43757186 | mysql | 183.79.135.206:55732  | DB名              | sleep       | 944      |                                                                       |                  |
| 43757260 | mysql | 183.79.135.206:55786  | DB名              | sleep       | 42       |                                                                       |                  |
| 43757279 | mysql | 183.79.135.206:55823  | DB名              | sleep       | 20       |                                                                       |                  |
| 43757284 | mysql | 183.79.135.206:55827  | DB名              | sleep       | 86       |                                                                       |                  |
| 43757302 | mysql | 183.79.135.206:55842  | DB名              | sleep       | 39       |                                                                       |                  |
| 43757306 | mysql | 183.79.135.206:55847  | DB名              | sleep       | 129      |                                                                       |                  |
| 43757307 | mysql | 183.79.135.206:55848  | DB名              | sleep       | 47       |                                                                       |                  |
| 43757353 | mysql | 183.79.135.206:55884  | DB名              | sleep       | 45       |                                                                       |                  |
| 43757356 | mysql | 183.79.135.206:55886  | DB名              | sleep       | 45       |                                                                       |                  |
| 43757374 | mysql | 183.79.135.206:55894  | DB名              | sleep       | 43       |                                                                       |                  |
| 43757385 | mysql | 183.79.135.206:55904  | DB名              | sleep       | 275      |                                                                       |                  |
| 43765522 | mysql | 183.79.135.206:35928  | DB名              | sleep       | 620      |                                                                       |                  |
| 43765933 | mysql | 183.79.135.206:36545  | DB名              | sleep       | 82       |                                                                       |                  |

(略)

+----------+-------+-----------------------+------------------+-------------+----------+------------------------------------------------------------------------+------------------+

GYAAAAAAAAAAAAAAAAAAA!

上記事でも書いていますが、特定のスキーマに対して長時間sleepしているプロセスのみkill する必要があります。

プロセスは以下のようなコマンドでkillできます。

mysql> kill プロセス番号

もしくはmysqlにログインせず
mysqladmin kill プロセス番号 -h localhost -u ユーザー名 -p

ただし、これら大量のプロセスを一個一個消していくのは骨が折れます。
そこで、条件を指定して一気に削除する方法を試しましょう

プロセスリストはSQLでも可取得能です。

SQLで条件を指定してプロセスIDを取得しましょう。
その後killコマンドで一気に削除します
mysqladmin killでは複数のIDを指定できますので1コマンドで完了します


information_schema.processlist に対して実行します。

use information_schema;
SELECT * FROM PROCESSLIST WHERE TIME > 59;

プロセス番号だけ取得するには以下のように指定します

SELECT GROUP_CONCAT(ID) FROM PROCESSLIST WHERE TIME > 59;


あとお好きな条件を指定しましょう
DBを限定するには以下のようにします

SELECT GROUP_CONCAT(ID) FROM PROCESSLIST WHERE TIME > 59 AND DB = "DB名";

ここで取得できたIDをコピーして、以下のようにプロセスを削除すれば完了です

mysqladmin kill 43401230,43401247,43401313,43401694,43401820,43401853,43401945,43401958,43757186,43757260.... -h localhost -u ユーザー名 -p