processlistで見つけた長時間クエリをKILLで止める

  • MySQL
  • Troubleshooting

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

長時間実行中のクエリをprocesslistから見つけて KILL で止めた時の手順メモ。

長時間実行中のクエリを見つける

SHOW PROCESSLIST で確認すると、Sending data 状態のまま881秒(約15分)実行中のクエリがあった。

mysql> show processlist;
+------+------+-----------+---------------+---------+------+--------------+---------------------------------------------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+------+------+-----------+---------------+---------+------+--------------+---------------------------------------------------------------------------+
| 1900 | root | localhost | example1 | Query | 0 | init | show processlist |
| 1957 | root | localhost | example2 | Query | 881 | Sending data | SELECT |
+------+------+-----------+---------------+---------+------+--------------+---------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Id は1957、実行時間は881秒。このクエリを止める。

KILLで止める

対象の Id を指定して KILL を実行する。

mysql> kill 1957;
Query OK, 0 rows affected (0.00 sec)

Query OK はKILLコマンド自体が正常に受理されたことを示しているだけで、対象クエリが止まったかどうかはこの時点では分からない。再度processlistを確認する。

mysql> show processlist;
+------+------+-----------+---------------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+------+------+-----------+---------------+---------+------+-------+------------------+
| 1900 | root | localhost | example2 | Query | 0 | init | show processlist |
+------+------+-----------+---------------+---------+------+-------+------------------+
1 row in set (0.01 sec)

id=1957が消えており、クエリは止まった。

補足: KILLは必ずしも即時ではない

今回はKILL実行後すぐにprocesslistから消えたが、KILL は必ずしもその場でクエリを中断するコマンドではないらしい(実機で常にこの挙動になるかは未確認)。

KILL が実際にやっているのはスレッドに「killされた」というフラグを立てることで、クエリ本体はそのフラグを定期的にチェックしているタイミングでしか反応しない。チェックのタイミングは処理内容によって異なり、大きい結果セットを行単位で読み進めている最中や、ソートバッファへの書き込み中など、チェック間隔が長い処理では反応が遅れることがあるらしい。

processlistの State が Killing になっている場合、これはフラグが立った後、実際に処理が中断されるまでの過渡状態を表している。今回のログでは Killing を経由したのか一瞬で終わったのかまでは分からない(Time が短いクエリだったため、たまたま即座に反応した可能性がある)。

大きめのテーブルスキャンや外部ストレージエンジン絡みのクエリなど、チェックポイントに到達しにくい処理を KILL した場合は、コマンド自体はQuery OKを返しても実際に消えるまで時間がかかるケースがあると考えておいた方が良さそう。processlistを再確認して消えていなければ、Killing 状態でまだ処理中なだけの可能性がある。