本ドキュメントは、開発者および運用担当者がMySQLのスロークエリログを迅速に設定し、低速なSQLを分析し、データベース実行時のスレッドブロッキングや負荷問題をトラブルシューティングするためのガイドです。
- スロークエリログの有効化
スロークエリの有効化には主に2つの方法があります:一時有効(再起動不要だが、再起動後に無効化)と永続有効(設定ファイル変更、再起動必須)。
1.1 一時的な有効化 (実行時)
本番環境で問題を一時的に調査し、データベースを再起動したくない場合に適用します。
SQL
-- 1. スロークエリログスイッチをONに
SET GLOBAL slow_query_log = 'ON';
-- 2. スロークエリ閾値を設定(単位:秒)
-- 例:1秒を超えるクエリを記録
SET GLOBAL long_query_time = 1;
-- 3. (任意)インデックス未使用のクエリを記録
SET GLOBAL log_queries_not_using_indexes = 'ON';
注意:
long_query_timeを変更しても、新規接続にのみ有効です。現在のセッションで即時反映させるには、SET long_query_time = 1;を実行する必要があります。
1.2 永続的な有効化 (設定ファイル)
長期監視に適しています。my.cnf(Linux)またはmy.ini(Windows)ファイルを修正します。
[mysqld] セクションに以下を追加または修正します:
Ini, TOML
[mysqld]
# スロークエリログを有効化
slow_query_log = 1
# スロークエリログファイルパス(絶対パス推奨)
slow_query_log_file = /var/lib/mysql/mysql-slow.log
# スロークエリ閾値(秒)
long_query_time = 1
# (任意)インデックス未使用のクエリを記録
log_queries_not_using_indexes = 1
修正後、MySQLサービスを再起動してください: systemctl restart mysqld
1.3 設定の確認
以下SQLを実行して設定が有効になったか確認します:
SQL
SHOW VARIABLES LIKE '%slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
- スロークエリの分析と表示
スロークエリログはテキストファイルとして直接確認できますが、公式のmysqldumpslowツールを使用して集約分析することもできます。これが最も一般的な方法です。
2.1 主なパラメータ説明 (mysqldumpslow)
-s: ソート方式 (Sort)c: アクセス回数 (Count)t: クエリ実行時間 (Time)l: ロック時間 (Lock time)r: 返された行数 (Rows)at: 平均クエリ時間-t: 上位何件を表示するか (Top)-g: 正規表現マッチング (Grep)
2.2 主な分析コマンド例
ターミナル(Shell)で実行:
mysqldumpslow -s t -t 10 /var/lib/mysql/mysql-slow.log
2. 「アクセス回数」でソートし、最も頻繁に実行される低速SQLを特定
Bash
mysqldumpslow -s c -t 10 /var/lib/mysql/mysql-slow.log
3. 「平均時間」でソートし、特定のテーブル名(例: user)を含むSQLを検索
Bash
mysqldumpslow -s at -t 10 -g "user" /var/lib/mysql/mysql-slow.log
- スレッドと負荷問題のトラブルシューティング
データベースのCPU使用率が急上昇または応答が遅延しているが、スロークエリログがまだ生成されていない(クエリがまだ終了していない)場合、スレッド状態をリアルタイムで確認する必要があります。
3.1 現在実行中のスレッドの確認
SHOW PROCESSLISTコマンドを使用します。
SQL
-- 現在の接続の上位100スレッドを表示
SHOW PROCESSLIST;
-- すべてのスレッドを表示(完全なSQL)
SHOW FULL PROCESSLIST;
3.2 注目すべきフィールド
| **フィールド** | **説明** | **異常状態 (State)** |
|---|---|---|
| **Id** | スレッドID | Kill操作に使用 |
| **User** | 実行ユーザー | - |
| **Time** | 経過時間(秒) | 値が大きい場合は注意が必要 |
| **Command** | コマンドタイプ | Query(クエリ実行中)、Sleep(アイドル状態) |
| **State** | **現在の状態(重要)** | Locked(ロック中)、Sending data(大量データ読み込み中)、Copying to tmp table(一時テーブルが大きすぎる) |
| **Info** | SQL文 | 実行中の具体的なSQL文 |
3.3 Information Schemaを使用した高度なフィルタリング
スレッドが非常に多い場合、SHOW PROCESSLISTでは確認しづらいため、システムテーブルを直接クエリします:
SQL
-- 実行時間が30秒を超える非Sleepスレッドをクエリ
SELECT * FROM information_schema.processlist
WHERE command != 'Sleep'
AND time > 30
ORDER BY time DESC;
3.4 停止したスレッドの強制終了
特定のSQL(IDが1234など)がデッドロックを引き起こしたりリソースを消費したりしている場合、強制終了できます:
SQL
KILL 1234;
- よくある問題のトラブルシューティング速查表
| **現象** | **考えられる原因** | **調査方法** |
|---|---|---|
| **CPU 100%** | 複雑なSQLが計算中または無限ループ | top -cでmysqlプロセスを確認 → SHOW FULL PROCESSLISTでStateがSending dataまたはStatisticsの高負荷SQLを探す。 |
| **I/O待機時間が高い** | フルテーブルスキャン、一時ディスク書き込み | スロークエリログを確認し、Rows\_examinedがRows\_sentを大幅に上回る文を注目;StateがCopying to tmp table on diskを確認。 |
| **接続数が上限に達** | 低速SQLの蓄積による接続解放遅延 | SHOW VARIABLES LIKE 'max\_connections';で現在の接続数と比較。 |