MySQLがレプリケーション遅延がALTERで治った

ある特定のテーブルに対するレプリケーションの遅延時間が、ここ数ヶ月間どんどん長くなり、場合によっては10分以上(!?)という状態になっていて困っていました。


データ量や更新頻度は、テーブルを作成した時とほぼ同じなのにどうして!と思って調べていました。

OPTIMIZE TABLEコマンドが使えそう

該当のこのテーブルは、他のテーブルと比較して、以下のような特徴があります。

  • データ量は多い
  • INDEXデータサイズも大きい
  • 更新頻度もかなり多い


このあたりが、レプリケーション遅延に影響しているのだろうと思い、調べていると以下のような情報を見つけました。

optimize tableでテーブルを最適化するだけでMyISAMはパフォーマンスが格段にアップするらしい(特にデータ更新が頻繁なテーブルの場合)。

MySQLとオープンソースに捧げる毎日:MySQLの管理など - livedoor Blog(ブログ)

はい。更新はかなり頻繁にあります。

時間がたつにつれて、テーブルに多くの変更が加わると、インデックスの効率が悪くなることがある。

  • 最も良く発生しそうな問題は以下の2つ。
    • ディスク上をデータブロックが移動することによるフラグメント化(断片化)
    • インデックス統計情報が不正確になること
  • 対応方法
    • MyISAMテーブルの場合、インデックスデータを最適化するのは簡単
      • OPTIMIZE TABLEコマンドを使用して、テーブルにインデックスを付け直すことができる。
      • MySQLは、テーブル内のすべてのレコードを読み直し、すべてのインデックスをつくり直す。その結果、良好な統計情報を備え、緊密にパックされたインデックスができる。
MySQLパフォーマンスチューニングのためのインデックスの基礎知識

確かに、INDEXデータサイズが作成当時よりも(3割ほど)大きくなってます。


と思いきや、ALTER TABLEしたほうがよさそう

ってことで、OPTIMIZE TABLEコマンド使えば、解決か!と思って検証しようとしましたが、ある日突然、遅延時間がほぼ無くなりました!


確認したところ、該当テーブルにカラム追加したことが解決した原因でした。つまり、「ALTER TABLE」したら治ったということです。不思議に思って、調べてみると、

最適化したい場合にはOPTIMIZE TABLEコマンドを使うのだが、これらのコマンドはWRITEだけでなくREADもブロックしてしまう。従って、メンテナンス中にWRITEは出来なくてもREADだけは可能にしたい、というような場合には、まずはALTER TABLEを試して見るといいだろう。テーブル定義の変更をせずに、テーブルを再作成したい場合には、次のようにALTER TABLEコマンドを実行するといい。

漢(オトコ)のコンピュータ道: ALTER TABLEを上手に使いこなそう。


おおなんと!ALTER TABLEにも同じ効果があるとは!!しかも、READをブロックしない分、適用できるシーンが多そうではないですか!!!

mysql> ALTER TABLE user_table ENGINE MyISAM;


とかって感じでやると、

このようにストレージエンジンを指定してやると、ALTER TABLEコマンドによってテーブルの再作成が行われるのである。もちろん、ストレージエンジンは元のテーブルと同じものを指定する必要がある。

漢(オトコ)のコンピュータ道: ALTER TABLEを上手に使いこなそう。

ということで、テーブルの定義は変更せずに、ALTER文を実行可能とのこと。もし次回以降、同じ症状が現れたら、この方法を試してみようと思います。