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