MySQL Error LogとGeneral Query Log:Sysadminのための本番環境エラー調査テクニック

MySQL tutorial - IT technology blog
MySQL tutorial - IT technology blog

午前2時にPagerDutyが鳴り響くとき

リリース後の激務を終え、深く眠りについている最中にシステムがダウン。サーバーにSSHでログインすると、CPU使用率は低く、RAMにも余裕があるのに、アプリケーションからはConnection Refusedが延々と出力されている。どこから手をつければいいか分からない時の無力感は凄まじいものです。

以前、原因不明でデータベースが新規接続をすべて拒否するという難題に直面したことがあります。Error Logを確認したところ、MySQLのopen_files_limit(ファイル記述子)が枯渇していることが判明しました。一晩中推測に頼るのではなく、制限を増やして再起動するだけで、わずか5分で解決できました。経験から言えるのは、ログを把握せずにMySQLを管理することは、ヘッドライトなしで霧の中を運転するようなものだということです。

この記事では、運用における「生命線」となる2種類のログ、Error Log(システムエラーの捕捉)とGeneral Query Log(全クエリの監視)に焦点を当てます。

1. MySQL Error Log:システム障害の記録

Error Logは、MySQLがクラッシュしたり起動できなかったりしたときに、まず最初に確認すべき場所です。エンジンが起動してから重大なエラーが発生するまでのすべての出来事が記録されます。

Error Logの適切な設定

本番環境では、ログをデフォルト設定のままにしないでください。管理やバックアップが容易になるよう、具体的なパスを指定しましょう。my.cnf(通常は/etc/mysql/にあります)を開き、以下の行を追加します。

[mysqld]
# ログを専用ディレクトリに保存
log_error = /var/log/mysql/error.log

# MySQL 8.0以降では、verbosityを使用して詳細度を制御
# 1: Errorのみ, 2: Error + Warning, 3: Error + Warning + Note
log_error_verbosity = 3

注意:本番環境でのMySQLの再起動はリスクを伴います。サービスを停止せずに現在のログの場所を確認するには、次のコマンドを使用してください。

SHOW VARIABLES LIKE 'log_error';

目を回さずにログを読むコツ

数GBもある重いファイルを開く代わりに、tailを使用して最新の行をリアルタイムで追跡しましょう:

tail -f /var/log/mysql/error.log | grep -i "error"

Out of memoryTable is marked as crashedToo many connectionsなどのエラーがすぐに表示されます。[ERROR]というタグがあれば、それはすぐに対処が必要なサインです。

2. General Query Log:24時間稼働の監視カメラ

Error Logがシステムの故障箇所を教えてくれるのに対し、General Query Logは「誰が何をしたか」を教えてくれます。サーバーが受信したすべての接続とすべてのSQLステートメントを記録します。

以前、このログのおかげで、古いモジュールが1秒間に数万回もSELECT 1のループを実行しているのを見つけたことがあります。そのクエリ自体に構文エラーはありませんでしたが、サーバーのIOPSを使い果たしていました。

General Query Logの有効化(慎重に使用してください!)

警告:General Logを有効にすると、サーバーのパフォーマンスが10%から15%低下する可能性があります。すべてのアクティビティを記録するため、ログファイルが非常に早く肥大化します。特定のトラブルシューティングが必要なときだけ有効にし、終わったらすぐに無効にしてください。

再起動せずにMySQLシェルで直接ログを有効にできます:

-- ログを有効化
SET GLOBAL general_log = 'ON';

-- 従来のテキストファイルに保存
SET GLOBAL log_output = 'FILE';
SET GLOBAL general_log_file = '/var/log/mysql/query_debug.log';

SQLを使って便利にログをクエリしたい場合は、出力をTABLEに変更します。データはmysql.general_logテーブルに保存されます。ただし、テーブルへの保存はファイルへの保存よりもストレージエンジンへの負荷が高くなります。

実際に必要になるのはどんな時?

  • アプリケーションが不要なクエリ(N+1クエリなど)を送信していないか確認する。
  • 機密性の高いテーブルへの不正アクセスが疑われる場合のアクセス監査。
  • Error Logでは捕捉できないビジネスロジックのエラーをデバッグする。

3. 手痛い教訓:ログでディスクをいっぱいにしない

ある同僚が, 5000リクエスト/秒のトラフィックがあるサーバーでGeneral Logをオフにするのを忘れたことがあります。結果、200GBのディスクが一晩で満杯になり、データベースが完全にフリーズしてしまいました。これは初歩的ですが、非常によくあるミスです。

解決策:Log Rotationの設定

Linuxのlogrotateを活用して、古いログを自動的に圧縮・削除しましょう。/etc/logrotate.d/mysql-serverファイルを以下の内容で作成します:

/var/log/mysql/*.log {
    daily
    rotate 7
    missingok
    compress
    postrotate
        mysqladmin flush-logs
    endscript
}

この設定により、直近7世代分のログが保持されます。システムが自動的に圧縮して容量を節約してくれるので、安心して眠ることができます。

4. ログ種類のクイック比較

用途を混同しないようにしましょう。以下の3つのルールを覚えておいてください:

  1. Error Log: MySQLが動作しない、またはクラッシュした時に使用。
  2. General Log: すべてのアクションを監査するために使用(ロジックのデバッグ時に有効化)。
  3. Slow Query Log: 低速なクエリ(1秒以上など)を見つけてインデックスを最適化するために使用。

実際には、Error Logは常にONにしておく必要があります。General Logは、データサンプリングのために短時間(例:15〜30分)だけ有効にするのが一般的です。

Lời kết

ログファイルを使いこなすことは、シニアデータベースエンジニアへの第一歩です。トラブルが発生してから設定ファイルを探すのではなく、今すぐError Logが正しく記録されているか、logrotateが動作しているかを確認しましょう。安定したシステム運用と、平穏な夜を過ごせることを願っています!

Share: