ちょっと硬派なコンピュータフリークのBlogです。

カスタム検索

2008-11-11

MySQL Clusterのディスクテーブルにおける注意点

MySQL Clusterには、バージョン5.1からディスクテーブルという機能が備わっているが、コイツが少し癖のあるやつなので今日はそのポイントについてまとめてみたい。

オトコたるものたまには真面目な話もしなければならないのである。

注意点。ディスクはメモリに比べてすごく遅い。以上!!

と言ってしまえばそれだけのことなのであるが、だったらなぜディスクテーブルなど使うのか?という話になってしまう。ディスクを使うのは、はディスクの方が同じ価格で購入できる容量が大きいからであって、MySQL Clusterにおけるディスクテーブルは速度を犠牲にして容量を稼ぐための手段であるといえる。残念ながら、ディスクの不揮発性により耐障害性を高めるための仕組みではないので誤解のないように注意されたい。

さて、ディスクテーブルを使うときは具体的にはどのようなシステム構成にすればいいのだろうか。以下に箇条書きで簡単にまとめてみたのでMySQL Clusterを構成する際の参考にしてほしい。各種パラメータの詳細はマニュアルに載っているのでそちらも参照すること。

1. トランザクションのタイムアウトを伸ばす。

デフォルトでは、1.2秒のうちに必要なロックを獲得できないと「デッドロック」という扱いになりトランザクションがタイムアウトしてしまう。しかしながら、1.2秒というのは非常に短い時間であり、ディスクに対するI/O、特に書き込みが大量に行われている状況では短期間にロックを獲得できない状況というのが容易に発生してしまう。高負荷時にロールバックが起きないようにしたいなら、以下の設定を施しておくといいだろう。

TransactionDeadlockDetectionTimeout=10000

このような設定をするとせっかくのMySQL Clusterのリアルタイム性が損なわれてしまうのではないか?と思われることだろう。その通りである!!ディスクの使用とリアルタイム性は両立しないのである。極限まで高いスループットを得たいのであればディスクは使うべきではない。なるべく低コストで容量を稼ぎたく、なおかつリアルタイム性がそれほど重要でないというような場合にのみディスクテーブルを使うべきである。テーブル定義において、大きなデータだけをディスクテーブルに格納するなど、細やかな使い分けをするといいだろう。(メモリにするかディスクにするかは、カラムごとに決められるのである。ただしインデックスの張られたカラムはディスクに格納することはできない。)

2. micro-GCPのタイムアウト値を伸ばす。

最近わけあって色々と調査をしていたのだが、MySQL Clusterはmicro-GCPというものを行ってレプリケーションの性能を上げている。(micro-GCPはMySQL Cluster 6.2から実装された機能である。)デフォルトでは4秒以内にmicro-GCPを完了させないとデータノードがシャットダウンする仕組みになっている。ディスクに対する書き込みが大量に行われている状況では、micro-GCPが間に合わない場合がある。特にバッチ系の処理が複数走ったりすると致命的である。この問題を回避するには以下の設定をするとよい。

TimeBetweenEpochsTimeout=32000

この値は32000(単位はミリ秒、つまり32秒)が最大値である。micro-GCPはレプリケーションの性能(一度にスレーブへ送られるデータ量の最小化+マスターとスレーブの遅延の最小化)を向上させるための機能である。このタイムアウト値を伸ばすということは、すなわちレプリケーションの性能を低下させる原因になりうるということである。

ディスクテーブルを利用する場合には、クラスタレプリケーションが遅延する可能性が高いということを覚えておくといいだろう。

また、MySQL Clusterでは、同時にコミットしたデータは同じタイミングでmicro-GCPが行われる。(厳密にいうと、同じEpochを持つデータは同じGCPに属する。)従って、同時にコミットする量を減らすことで、micro-GCPが間に合わない可能性を減らすことが可能なのである。

3. ディスクテーブルに対するバッファを大きくとる。

ディスクテーブルでは、2種類のバッファがある。ディスクページバッファとUndoバッファである。前者はテーブルスペースに対するキャッシュであり、後者はUndoログに対するバッファである。ディスクテーブルをメインで利用する場合にはそれぞれ大きめの値を割り当てておくとよい。特に更新が多い場合には大きいバッファを利用するべきである。最低でも一度にコミットするデータサイズの数倍以上は確保するべきであろう。

DiskPageBufferMemory=2048M
SharedGlobalMemory=512M

UndoバッファはCREATE LOGFILE GROUPステートメントでサイズを指定することが可能である。

DiskPageBufferMemoryの適切なサイズについては、マニュアルに説明があるのでそちらも参照してほしい。

4. テーブルスキャンをしない。

スキャンをするとディスクページバッファキャッシュのヒット率が格段に下がってしまう。ディスクテーブルを使う場合には、必ずインデックスを活用してデータをピンポイントでゲットするように工夫しよう。レポートの作成など、どうしてもテーブルスキャンが必要な場合には、負荷の少ない時間を選ぶか、クラスターレプリケーションを用いて負荷分散すると良い。

5. GCP/LCPとは別のディスクを利用する。

現在のところ、ディスクテーブルのデータファイルを配置するディレクトリを決定するためのオプションはなく、デフォルトではDataDir=FileSystemPathにデータファイルおよびUndoファイルが作成されてしまう。データファイルやUndoファイルを他の場所に作成したい場合には、CREATE TABLESPACEステートメントやCREATE LOGFILE GROUPステートメントにおいて、絶対パスでファイル名を指定する必要がある。

mysql> CREATE LOGFILE GROUP lg1
    -> ADD UNDO FILE '/another/dir/undo-1.dat'
    -> INITIAL_SIZE 10240M
    -> UNDO_BUFFER_SIZE 256M
    -> ENGINE NDB;

また、MySQL ClusterではUndoファイルおよびデータファイルは、大きなファイルを一つ作成するのではなく、複数のファイルを使用すると性能が向上する。これは、MySQL Clusterが一つのファイルにつき一つのI/Oスレッドを作成することに起因する。100GBのデータファイルを作成するより、25GBのデータファイルを4つ作成した方が性能がイイということである。これは知ってて損はないだろう。ファイル数は4つ程度が適度である。

しかし、ディスクは遅いので性能が向上すると言っても限界があるのをお忘れなく!!

0 コメント:

コメントを投稿