MySQLに重いSQLを投げて、帰って来ない時は
重い集計SQLなんかを実行したけど、いつまでたっても帰ってこない時の対処についてです。
まずは、topコマンドで確認します。大抵、以下の例のように、mysqldがリソースを使い切っています。
[root]# top top - 16:20:17 up 15 days, 6:50, 1 user, load average: 5.39, 5.14, 5.04 Tasks: 177 total, 2 running, 175 sleeping, 0 stopped, 0 zombie Cpu(s): 33.7%us, 66.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.3%st Mem: 1048752k total, 826136k used, 222616k free, 194584k buffers Swap: 562264k total, 4492k used, 557772k free, 277856k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2640 mysql 15 0 85704 42m 3664 S 398.6 4.1 2120:30 mysqld 1 root 15 0 2084 656 560 S 0.0 0.1 0:00.03 init 2 root RT -5 0 0 0 S 0.0 0.0 0:00.44 migration/0
そこで、まず、MySQLに接続し「SHOW PROCESSLIST」コマンド結果を確認します。
[root]# mysql --defaults-file=/db/mysql/data/my.cnf -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 22802 Server version: 5.1.34-community-log MySQL Community Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> SHOW PROCESSLIST; +----+------+-----------------+------+---------+-------+----------------------+----------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------------+------+---------+-------+----------------------+----------------------------------+ | 10 | root | localhost:46214 | test | Query | 23852 | Copying to tmp table | SELECT COUNT(*) FROM `accesslog` | | 12 | root | localhost:60469 | test | Query | 20332 | Waiting for table | TRUNCATE TABLE `accesslog` |
これは、一つ目の重いSQLが抜けないために、その後のTRUNCATE文がずっと待たされている状態と言えます。なので、この重いSQLをkillします。killコマンドは、「kill (対象SQLの)Id」の構文で実行します。
mysql> kill 10; Query OK, 0 rows affected (0.00 sec) mysql> SHOW PROCESSLIST; +----+------+-----------+------+---------+-------+-------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+------+---------+-------+-------+------------------+ | 10 | root | localhost | test | Query | 23852 | NULL | SHOW PROCESSLIST |
そうすると、おそらく、待たされていた後続のSQLも流れて、PROCESSLISTには何も出なくなったりすると思います。
(補足)SHOW PROCESSLISTコマンドについて
詳しくは、http://dev.mysql.com/doc/refman/5.1-olh/ja/show-processlist.html を参照してください。
出力カラムは次の意味を持っています。
- Id : 接続識別子。
- User : ステートメントを発行した MySQL ユーザ
- Host : ステートメントを発行しているクライアントのホスト名
- db : デフォルトデータベース
- Command : スレッドが実行しているコマンドのタイプ
- 時刻 : スレッドが現在の状態になってからの秒数
- State : スレッドの状態*1
- Info : スレッドが実行中のステートメント
FULL オプションについて
通常、Info 列に表示されるクエリは100文字を越えると省略されますが、FULL オプションを指定すると、省略せずクエリの全文が表示されます。その際、表示が崩れるようであれば\G オプションでクエリ結果を垂直表示すると見やすくなります。
mysql> SHOW FULL PROCESSLIST \G;