はじめに
MySQLを安定運用するには「何かおかしい」と気づく前に、普段から何を監視すべきかを把握しておく必要があります。本記事は『MySQL運用・管理 実践入門』第7章6節の内容をもとに、死活監視から各種異常検知まで実務で使える監視項目をまとめています。
なお、AWSのRDSを利用している場合の読み替えポイントも合わせて記載しています。
監視の全体像
7-6節では監視項目を大きく3つに分類しています。
- 死活監視:MySQLが正常に動作しているか
- ハードウェアリソースの監視:CPU・メモリ・ディスク・ネットワーク
- MySQL内部の異常検知:トランザクション・クエリ・レプリケーション
1. 死活監視
プロセスの確認だけでは不十分
単純にプロセスが起動しているかだけを確認する方法には落とし穴があります。
ps aux | grep mysqld | grep -v grep
NFS(Network File System)やSDS(Software Defined Storage)を使っている環境では、ネットワーク障害でストレージがハングしても ps コマンドは正常に見えることがあります。
ディスクへの書き込みまで確認する
本当に正常かどうかはディスクへの書き込みが成功するまで確認して初めてわかります。
-- 監視用テーブルを作成
CREATE TABLE alive_monitoring (
updated_at datetime NOT NULL PRIMARY KEY
);
-- 定期的に更新(これが成功すればディスク書き込みまで正常)
UPDATE alive_monitoring SET updated_at = NOW();
このテーブルを監視プラットフォームから定期的に更新し、タイムアウトや失敗を検知する仕組みを作ります。
注意:このテーブルが肥大化しないよう、行を増やし続けるのではなく1行を更新し続ける設計にする
死活監視に失敗した場合の対応フロー
死活監視失敗
↓
mysqld プロセスが起動しているか確認(ps コマンド)
↓
エラーログに原因が出ていないか確認
↓
OS のログ(journalctl)に異常がないか確認
↓
原因を取り除いてから mysqld を起動
RDS を使っている場合
RDSはマネージドサービスのため、プロセス管理はAWS側が行います。RDSイベント通知とCloudWatchアラームを組み合わせることで死活監視を代替できます。alive_monitoring テーブルを使った書き込み確認は、ストレージ障害まで含めた厳密な確認が必要な場合に追加で実施する価値があります。
2. ハードウェアリソースの監視
CPU 利用率
閾値の目安:高負荷時でも50〜60%以下
CPU利用率が100%に達してしまうと、管理者による緊急対応(ログ確認・クエリのKILLなど)自体が難しくなります。
# mysqld のCPU利用率を確認
pidstat 1 -p `pidof mysqld`
CPU高騰の主な原因と対処:
| 原因 | 対処 |
|---|---|
| 実行計画が悪いクエリ(フルスキャンなど) | インデックス追加・クエリ書き換え |
| ロックの競合による待ち時間 | トランザクション設計の見直し |
| 性能限界 | スケールアップ・シャーディング |
RDS の場合:CloudWatch の CPUUtilization メトリクスを監視。70%超で警告アラームを設定するのが一般的です。
ディスク利用率
閾値の目安:80%以下
Disk Fullになると多くのクエリがハングアップします。DELETE ステートメントもバイナリログの出力を伴い、OPTIMIZE TABLE も余剰の領域を必要とするため、Disk Fullになってからでは対処が非常に難しいのが特徴です。
注意点として、ディスク全体の容量だけでなく最大ファイルサイズのテーブルがディスク容量の半分を超えないことも確認しましょう。ALGORITHM=COPY でしか実行できないDDLや pt-online-schema-change などの実行時に同程度のディスク容量の空きが必要になります。
# ディスクへのI/O状況確認
iostat -d
RDS の場合:CloudWatch の FreeStorageSpace を監視。絶対値(例:残り20GB以下)でアラートを設定します。
メモリ利用率
指標:Swap 領域を使わないこと
MySQLは innodb_buffer_pool という大きなメモリ領域を確保して動きます。これがSwapアウトされると毎回ディスクアクセスが発生し、急激にパフォーマンスが悪化します(スラッシング)。
メモリ利用率のパーセントで閾値を決めることは難しいため、Swapを使っていないことを指標にするのが現実的です。
$ free -m
total used free buff/cache available
Mem: 15982 915 14295 0 771 14787
Swap: 0 0 0 ← 0であれば正常
対処:
-
innodb_buffer_pool_sizeを下げる - バイナリログのページキャッシュを一時的に解放する
sudo sh -c "echo 1 > /proc/sys/vm/drop_caches"
RDS の場合:CloudWatch の FreeableMemory を監視。数百MB以下に近づいたらアラートを設定します。
ネットワーク帯域
閾値の目安:90%程度で原因調査
近年のネットワーク環境では帯域がボトルネックになることは少ないですが、意図しないほど大量のデータを転送している場合はクエリを見直す必要があります。
よくある原因:
-
SELECT *で不要なカラム(BLOBやJSONなど)まで取得している - 大量データを扱うバッチ処理が帯域を使い切っている
# NICごとのデータ転送量確認
sudo ifstat
RDS の場合:CloudWatch の NetworkReceiveThroughput / NetworkTransmitThroughput を監視します。
3. MySQL内部の異常検知
auto_increment 値の枯渇
閾値の目安:型の上限の80%で検知
auto_increment を指定したカラムが数値型の最大値に達すると、それ以上レコードを追加できなくなります。型の拡張(例:INTからBIGINT)には ALGORITHM=COPY での実行が必要なため、対応完了まで時間がかかります。気づいたときには手遅れになりやすい項目です。
-- 全テーブルの auto_increment 値を確認
SELECT
t.TABLE_SCHEMA,
t.TABLE_NAME,
t.AUTO_INCREMENT,
c.COLUMN_NAME,
c.DATA_TYPE
FROM information_schema.TABLES t
JOIN information_schema.COLUMNS c
ON t.TABLE_SCHEMA = c.TABLE_SCHEMA
AND t.TABLE_NAME = c.TABLE_NAME
WHERE t.TABLE_SCHEMA NOT IN ('mysql')
AND t.AUTO_INCREMENT IS NOT NULL
AND c.EXTRA LIKE '%auto_increment%';
各データ型の最大値(符号なし):
| 型 | 最大値 |
|---|---|
| INT UNSIGNED | 約42億(4,294,967,295) |
| BIGINT UNSIGNED | 約1844京 |
RDS の場合:CloudWatchには対応するメトリクスがないため、Lambdaで定期的に上記クエリを実行してCloudWatchカスタムメトリクスに送る構成が現実的です。
長時間実行されているトランザクション
長時間トランザクションを放置すると以下の問題が発生します:
- undoログが肥大化してディスクを圧迫
- ガベージコレクションが進まずパフォーマンス悪化
- レプリケーション遅延の原因になる
INNODB_TRX テーブルで実行時間を確認し、問題のあるトランザクションを特定してKILLします。
-- 実行中のトランザクションと実行クエリを取得
SELECT
trx_started,
processlist_host,
processlist_user,
sql_text
FROM information_schema.INNODB_TRX trx
INNER JOIN performance_schema.threads th
ON trx.trx_mysql_thread_id = th.processlist_id
INNER JOIN performance_schema.events_statements_history e
ON th.thread_id = e.thread_id;
-- 特定できたらKILL(trx_mysql_thread_id を使う)
KILL <trx_mysql_thread_id>;
注意:サービスにとって重要なトランザクションをKILLするとロールバックが発生し影響が大きくなる場合があります。原因を把握してから対処しましょう
スロークエリ数の急増
スロークエリの累積件数の差分を一定間隔で取ることで、急増を検知できます。
SHOW GLOBAL STATUS LIKE 'Slow_queries';
スロークエリが多すぎてノイズになる場合は long_query_time を大きくすることも検討します。pt-query-digest などの集計ツールで定期的にレポートを作成すると、イベントや季節要因の傾向把握にも役立ちます。
レプリケーションの状態と遅延
レプリケーションの状態と遅延秒数を確認します。
SHOW REPLICA STATUS\G
確認すべきカラム:
| カラム | 正常な値 | 異常のサイン |
|---|---|---|
Replica_IO_Running |
Yes | No |
Replica_SQL_Running |
Yes | No |
Seconds_Behind_Source |
0に近い | 増加し続けている |
レプリケーションが遅延しているということは、レプリカにアクセスしてSELECTしたデータは「過去のものが表示される」ということです。これがアプリケーションにどれだけ影響するかはサービス要件次第なため、「何秒以上の遅延を異常とするか」はサービスに合わせて設定します。
遅延の原因と対処:
| 原因 | 対処 |
|---|---|
| 小さいトランザクションが大量 |
replica_parallel_workers を増やして並列度を上げる |
| 大きなトランザクション・ALTER TABLE | 実行前にレプリカへの影響を考慮する。innodb_flush_log_at_trx_commit=2, sync_binlog=0 で一時的に速度を上げる(永続性は犠牲になる) |
RDS の場合:CloudWatch の ReplicaLag メトリクスを監視します。
まとめ:監視項目と閾値の一覧
| 監視項目 | 閾値の目安 | 確認方法 | RDS代替 |
|---|---|---|---|
| 死活監視 | タイムアウト・接続失敗 |
alive_monitoring テーブル更新 |
RDSイベント通知 |
| CPU利用率 | 50〜60%以下 |
pidstat, top
|
CloudWatch CPUUtilization
|
| ディスク利用率 | 80%以下 | df -h |
CloudWatch FreeStorageSpace
|
| メモリ(Swap) | Swapを使わない | free -m |
CloudWatch FreeableMemory
|
| ネットワーク帯域 | 90%程度で調査 | ifstat |
CloudWatch ネットワークメトリクス |
auto_increment 値 |
型上限の80% | information_schema.TABLES |
Lambdaカスタムメトリクス |
| 長時間トランザクション | 検知したらKILL | INNODB_TRX |
Performance Insights |
| スロークエリ数 | 急増を検知 | SHOW GLOBAL STATUS LIKE 'Slow_queries' |
CloudWatch Logs(スロークエリログ) |
| レプリケーション遅延 | サービス要件次第 | SHOW REPLICA STATUS |
CloudWatch ReplicaLag
|
各閾値はあくまで目安です。サービスの性質やスケールによって適宜調整してください。