MySQL の SHOW PROCESSLIST で実行中クエリを監視する

SHOW PROCESSLIST は、MySQL サーバーで現在実行中のスレッドを一覧表示するコマンドです。遅いクエリの特定、ロック待ちの調査、負荷状況の把握に役立ちます。

基本的な使い方

SHOW PROCESSLIST;

デフォルトでは Info 列(実行中のクエリ)が 100 文字で切り詰められます。完全なクエリを見るには FULL を付けます。

SHOW FULL PROCESSLIST;

出力の見方

意味
Id接続 ID(KILL で使用)
User接続ユーザー
Host接続元ホスト
db使用中のデータベース
Command実行中のコマンドタイプ
Time現在の状態の経過秒数
Stateスレッドの状態
Info実行中の SQL(NULL の場合もあり)

Command 列の主な値

Query

SQL クエリを実行中。Info 列に実際のクエリが表示されます。

Sleep

クライアントからの次のコマンドを待機中。アイドル状態です。

Connect

レプリカがソースに接続中、または接続処理中。

Killed

KILL コマンドで終了を指示されたが、まだ終了していない状態。

State 列の重要なパターン

State 列はクエリ実行のどの段階にいるかを示します。問題を示唆するものを覚えておきましょう。

State意味注意点
Sending dataクエリ結果を読み取り中長時間続くと問題
Waiting for table metadata lockDDL 待ちALTER TABLE がブロックされている可能性
Copying to tmp table一時テーブルにコピー中大量データで発生
Sorting resultソート処理中filesort が発生
Lockedテーブルロック待ちMyISAM で発生しやすい

問題のあるクエリを見つける

長時間実行中のクエリを見つけるには、Time 列でフィルタします。

SELECT * FROM information_schema.PROCESSLIST
WHERE Command = 'Query' AND Time > 10
ORDER BY Time DESC;

これで 10 秒以上実行中のクエリが見つかります。

performance_schema を使う方法

より詳細な情報が必要な場合は、performance_schema を使います。

SELECT 
    THREAD_ID,
    PROCESSLIST_USER,
    PROCESSLIST_HOST,
    PROCESSLIST_DB,
    PROCESSLIST_COMMAND,
    PROCESSLIST_TIME,
    PROCESSLIST_STATE,
    PROCESSLIST_INFO
FROM performance_schema.threads
WHERE PROCESSLIST_COMMAND = 'Query';

問題のあるクエリを停止する

特定のクエリを強制終了するには KILL コマンドを使います。

-- 接続を終了(クエリ + 接続)
KILL 12345;

-- クエリだけを終了(接続は維持)
KILL QUERY 12345;

12345 は SHOW PROCESSLIST で確認した Id です。

ロック待ちの調査

Waiting for table metadata lock などが表示されている場合、何がロックを保持しているか調べます。

SELECT 
    r.trx_id AS waiting_trx_id,
    r.trx_mysql_thread_id AS waiting_thread,
    r.trx_query AS waiting_query,
    b.trx_id AS blocking_trx_id,
    b.trx_mysql_thread_id AS blocking_thread,
    b.trx_query AS blocking_query
FROM information_schema.innodb_lock_waits w
JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;

MySQL 8.0 以降では、performance_schema.data_lock_waits を使います。

Sleep 接続の監視

Sleep 状態の接続が多すぎると、max_connections を圧迫します。

SELECT COUNT(*) AS sleep_count 
FROM information_schema.PROCESSLIST 
WHERE Command = 'Sleep';

長時間 Sleep している接続は、wait_timeout の設定で自動切断するか、アプリケーション側のコネクションプールを見直します。

継続的な監視

瞬間的なスナップショットだけでなく、継続的な監視が重要です。

監視ツール(PMM、Datadog など)でプロセスリストを記録
スロークエリログと併用
長時間クエリのアラート設定
ロック待ちの頻度を追跡

pt-kill の活用

Percona Toolkit の pt-kill を使うと、条件に合うクエリを自動的に停止できます。

# 60秒以上実行中のSELECTを表示(実際には停止しない)
pt-kill --host=localhost --user=root \
  --busy-time 60 --match-command Query \
  --match-info "SELECT" --print

# 実際に停止する場合は --kill を追加

本番環境では慎重に使う必要がありますが、暴走クエリへの自動対処として有効です。

SHOW PROCESSLIST は MySQL の「今」を見るための基本ツールです。問題発生時に素早く状況を把握できるよう、出力の読み方に慣れておきましょう。