MySQLの無限ループを停止させる方法

開発中にうっかりやってしまいがちなミスが無限ループのSQLコマンドを発行してしまうことです。 もしMySQL自体を停止させようとしている人はちょっと待って!

無限ループ時の動作

サーバー自体は問題なさそうなのに(ちょっと遅いかな…ぐらい)、MySQLを利用した処理が非常に重い場合は、無限ループの(正確には無限ループしているように見える時間のかかる)クエリー(スロークエリ)を発行してしまった可能性があります。

実際にtopコマンドで見てみましょう。

$top
top - 06:32:51 up 226 days,  9:46,  1 user,  load average: 1.69, 0.53, 0.24
...(中略)...
PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
28351 mysql     15   0  111m  16m 5456 S 99.9  1.6   8:34.78 mysqld
1 root      15   0  2064  100   68 S  0.0  0.0   0:52.53 init
1442 root      17   0 11776 3016 2392 S  0.0  0.3   0:00.02 sshd

ギャー! これはヤバイっす! ロードアベレージも1を超えちゃってます。。

MySQL停止(mysqld stop)は待って!

「/etc/init.d/mysqld stop」などでMySQL自体を停止しようとしている人はちょっと待ってください。

MySQLでは中でどのようなプロセスが動作しているのか「mysqladmin processlist」で見ることができます。

$ mysqladmin processlist -u root -p
Enter password: (MySQLのrootパスワードを入力)
+--------+------------------+-----------+----+---------+------+----------------------+---------------------------------------------------+
| Id     | User             | Host      | db | Command | Time | State                | Info                                              |
+--------+------------------+-----------+----+---------+------+----------------------+---------------------------------------------------+
| 443123 | myuser           | localhost | m  | Query   | 104  | Copying to tmp table | SELECT  SQL_CALC_FOUND_ROWS mytable.myid FROM (   |
| 443134 | root             | localhost |    | Query   | 0    |                      | show processlist                                  |
+--------+------------------+-----------+----+---------+------+----------------------+---------------------------------------------------+

「Id」列が「443123」のプロセスを見てください。 「Time」の列の数値が多く、時間がかかっています。 「State」列を見ると、どうやら一時的にテーブルをコピーしているのが原因のようですね。

厳密には、メモリーに一時テーブルをコピーするだけでは足りず、ハードディスクにコピーしてしまっています。 これは典型的なスロークエリの症状です。

特定のMySQL内プロセスを「mysqladmin kill」で削除する

特定できたプロセスは「mysqladmin kill」コマンドを使って停止させることができます。

$ mysqladmin kill 443123 -u root -p
Enter password: (MySQLのrootパスワードを入力)

では、もういちど「mysqladmin processlist」コマンドで見てみましょう。

$ mysqladmin processlist -u root -p
Enter password: (MySQLのrootパスワードを入力)
+--------+------+-----------+----+---------+------+-------+------------------+
| Id     | User | Host      | db | Command | Time | State | Info             |
+--------+------+-----------+----+---------+------+-------+------------------+
| 443165 | root | localhost |    | Query   | 0    |       | show processlist |
+--------+------+-----------+----+---------+------+-------+------------------+

おお! ちゃんと消えてくれました!

MySQLの基本を知っていても、参照数の減らし方やインデックスの使われ方といった仕様をきちんと理解していない人は度々陥ってしまうミスです。 しっかり勉強しておきましょうね!

このページをシェアする

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

2010-03-20