MySQL innodb_flush_method = O_DIRECTの検討

MySQL InnoDBのパラメータでinnodb_flush_methodというものがあります。これはUNIX/Linuxにおいてデータファイル、ログファイルの読み書き方式を指定するためのもので、マニュアルの13.6.3. InnoDB Startup Options and System Variablesによると以下の3種類の設定が可能とされています。

  • 無指定(fdatasync):デフォルトの設定です。特別なフラグなしでファイルをオープンし、書き込み時にfsync()を行います。
  • O_DSYNC:データファイルについてはfdatasyncと同じです。ログファイルについてO_SYNCフラグをつけてファイルをオープンします。
  • O_DIRECT:データファイルについてO_DIRECTフラグをつけてファイルをオープンします。ログファイルについてはfdatasyncと同じです。

今回はこのパラメータをO_DIRECTに設定すべきか否か、というところを考えていきたいと思います。

Direct I/Oとは

O_DIRECTフラグをつけてファイルをオープンすると、OSの持つDirect I/Oという機能を利用することができます。Direct I/OについてはITproの記事が図入りで分かりやすいと思います。要するにこれはOSのキャッシュ機構をバイパスする機能であり、RDBMSは自前でデータをキャッシュするのだからOSのキャッシュ機構はいらないだろう、という話です。
RDBMSにおけるDirect I/Oの利用については、以下の書籍でも解説されています。

試験の概要

ではDirect I/Oを利用するとMySQLの性能特性はどのように変化するのでしょうか。ウェブ上では実際の性能データが見つからなかったので、拙作JdbcRunnerの動作テストも兼ねて簡単に測定してみました。

試験パラメータとして以下の3つを変化させ、合計70パターンの測定を行いました。

  • TPC-Cスケールファクタ:2、5、10、20、50
  • innodb_buffer_pool_size:8MB、16MB、32MB、64MB、128MB、256MB、512MB
  • innodb_flush_method:無指定(fdatasync)、O_DIRECT

TPC-Cのスケールファクタは1あたり約100MBのデータ量となります。スケールファクタ50であれば約5GBです。

試験結果

以下、試験結果です。横軸はSがTPC-Cスケールファクタ、BがInnoDBバッファプールサイズを表しています。

ほとんどの試験パターンでDirect I/Oを利用した方が性能が低くなりました。Direct I/Oを利用して性能が向上したのは、TPC-Cスケールファクタ2におけるInnoDBバッファプールサイズ256MB、512MBの設定、それからTPC-Cスケールファクタ5におけるInnoDBバッファプールサイズ512MBの設定のみです。

  • fdatasyncの方が性能が高いのは、InnoDBバッファプールにないデータがOSのファイルキャッシュにある場合があり、それによってディスクI/Oが軽減されるため。つまりOSのファイルキャッシュがInnoDBバッファプールに対する二次キャッシュのような存在となっている
  • しかし、OSのファイルキャッシュを期待してfdatasyncの設定でInnoDBバッファプールサイズを極端に小さくしても、あまり良い性能は得られない
  • O_DIRECTがfdatasyncに比べて同等以上の性能を発揮するためには、(1)すべてのデータがInnoDBバッファプールに収まる、(2)物理メモリの半分程度をInnoDBバッファプールに割り当てる、のいずれかの条件を満たす必要がある
  • すべてのデータがInnoDBバッファプールに収まる条件では、O_DIRECTの性能がfdatasyncを上回る。これは書き込みの際にOSのファイルキャッシュを制御しなくてよいためである

考察

O_DIRECTはMySQL自体の性能を上げるためというよりは、MySQLが使用するメモリ量を意図的に制限するためのパラメータだととらえた方がよさそうです。基本的な方針としては、O_DIRECTを用いるとともにInnoDBバッファプールに物理メモリの半分を割り当てるのがよいと思いますが、これと異なる設定が適している場合もあるでしょう。

  • MySQL以外に激しくディスクI/Oを行うプロセスが存在する場合は、O_DIRECTを用いるとともにInnoDBバッファプールサイズを小さく抑える
  • MySQLの再起動をよく行う環境では、fdatasyncを用いOSのファイルキャッシュを利用することで再起動直後の性能劣化を軽減する
  • MySQLを複数立ち上げる環境で事前の容量見積もりが難しい場合は、fdatasyncを用いてOSのファイルキャッシュを利用し、それぞれのInnoDBバッファプールサイズを小さくする

試験セット

今回の試験に用いたプログラム、スクリプト、ログファイル、グラフをダウンロードできるようにしておきました。

性能特性はハードウェア構成によっても変わってきますから、機会があればみなさんの環境で試してみることをおすすめします。