Road To Nowhere

主にWebまわりのエンジニア的なお仕事に関するようなことのあれこれ。

スレーブのリレーログが増殖してサーバのディスクを圧迫した

とある日、スレーブの1台からディスク容量がいっぱいになっているというアラートがきたので、そのときのトラブルシューティングやあれこれ。

環境と現象

  • MySQL: 5.5.8
  • MySQLレプリケーション機能を使って、マスター1台 x 複数のスレーブ という構成で運用している。
  • とある日、スレーブの1台からディスク容量がいっぱいになっているというアラートがくる。(nagiosで監視)
  • show slave status で調べると、そのスレーブだけデータの同期(Slave_SQL_Running)が止まっていた。
  • 実際どのファイルがディスクを圧迫しているか調べると、リレーログ(ファイル名はhost-relay-bin.00XXXX)がやたら増えているのが判明した。

解決方法

  • エラーログ(host.err)やshow slave statusで同期が止まった原因を特定&対応(またはskip slave なんて手もあるが・・)して、slave startを実行。つまり正常に同期を再開させた。
    • 実際に何をして同期を再開させたかは運用事情が複雑なので避けるが、更新クエリで参照しているテーブルがこのスレーブだけなかったので、他のサーバからdumpしてもってきたということにしておく。
  • 同期が進むと自動的に古いものからリレーログがなくなっていって、無事ディスクの容量圧迫問題は解決した。

なぜそれで解決したのか?

解決するのに時間はかからなかったが、リレーログの役割やレプリケーションの仕組みについて理解を深めるのに役立ったので、メモがてら書いてみる。

1. マスタで処理された更新系のクエリが逐次、マスタのバイナリログに記録される。
2. スレーブのI/OスレッドがマスタのBinlog Dumpスレッドに接続する。
3. マスタのBinlog Dumpスレッドは、バイナリログの内容をどんどん送信する。Binlog Dumpスレッドはこの処理を繰り返す。
4. スレーブのI/Oスレッドは、受け取ったマスタのバイナリログをスレーブ内に保存する。これをリレーログと呼ぶ。I/Oスレッドはこの処理を繰り返す。
5. スレーブのSQLスレッドは、リレーログからクエリを読み取って実行する。SQLスレッドはこの処理を繰り返す。

  • 手順1〜3は特に難しくなく、誰もが想像している通りの動きではないかと思う。
  • 手順4に注目。スレーブはマスタのバイナリログの情報を受け取ったらそのままスレーブのデータに反映(もしくはSQLを実行)するのではなく、一度リレーログに書き出すということ。これはなるほどと思う人が少なくないんじゃないか。
  • 今回のトラブルでは、データの同期(つまりSQLスレッド)が止まっていた間もI/Oスレッドは動いていて、マスタからバイナリログの情報を受け取ってリレーログに溜め込み続けていたということになる。
  • また上にも書いたが、データの同期が止まった問題を解決してSQLスレッドを再開(slave start)すると、リレーログからマスタの更新情報をスレーブのデータに反映して、反映が終り次第、ファイル単位でリレーログはなくなっていった。


バイナリログとリレーログ、SQLスレッドとI/Oスレッド。
このあたりのレプリケーションの基本のおさらいができて、有意義なトラブルシューティングだった。(ポジティブシンキングv( ̄ー ̄)v)