2009年6月1日月曜日

fdatasync

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
今月のカーネルウオッチでfdatasyncが出てきたのでpythonでどうなっているか見てみることにした。

そもそもfdatasyncってなにさ?

man page of fsyncより

fsync() は、ファイル記述子 fd で参照されるファイルの内部で持っているデータ (つまりバッファキャッシュページ) のうち修正されたデータを、そのファイルが属するディスクデバイス (またはその他の永続ストレージデバイス) に転送 (「フラッシュ」) する。この呼び出しは転送が終わったとデバイスが報告するまでブロックする。またファイルに結びついたメタデータ情報 (stat(2) 参照) もフラッシュする。

fsync() の呼び出しは、ファイルが存在しているディレクトリのエントリがディスクへ書き込まれたことを保証するわけではない。保証するためには明示的にそのディレクトリのファイル記述子に対しても fsync() する必要がある。

fdatasync() は fsync() と同様であるが、メタデータの扱いが異なる。 fdatasync() は、それ以降のデータ読み込みを正しく扱うためにそのメタデータが必要にならない限り、変更されたメタデータをフラッシュしない。例えば、 st_atime や st_mtime (それぞれ最終アクセス時刻、最終修正時刻; stat(2) 参照) の変更はフラッシュを必要としない。なぜならこれらはそれ以降のデータ読み込みを正しく扱うために必要ではないからである。一方、ファイルサイズ (ftruncate(2) では st_size) の変更はメタデータのフラッシュが必要である。 fdatasync() の狙いは、全てのメタデータをディスクと同期する必要のないアプリケーションに対して、ディスクアクセスを減らすことである。


データベースを作っている人は気にするし使います。


まずは標準ライブラリだが、osモジュールにはちゃんとfdatasyncがある。posixmodule.cを覗くとなかで読んでいるのがわかる。

fdatasync(fd)
ファイル記述子 fd を持つファイルのディスクへの書き込みを強制します。メタデータの更新は強制しません。利用できる環境: Unix

かなり昔からあるみたいで、2.3のときにfsyncとfdatasyncは別々に調べなきゃ駄目よbugがあった。


で、次にどんなアプリが使っているか?なのだが、ソースコード検索してみる。

mved-1.0
mved - An editor-focused multiple file move utilityだ、そうな。

tmpfd, tmpfilename = mkstemp()
try:
for name in oldnames:
write(tmpfd, '%s\n' % name)
fdatasync(tmpfd)
except IOError, e:
giveup("%s: %s", (tmpfilename, str(e)))

なにやらfile systemを読み書きするものらしい。

def fsync(self, isfsyncfile):
self._fflush()
if isfsyncfile and hasattr(os, 'fdatasync'):
os.fdatasync(self.fd)
else:
os.fsync(self.fd)

あまり引っかからない。file objectのflushでも読んだほうがいいのだろうか?そう思ってObjects下をgrepするも成果なし。

とまあ、ほとんどのpython userには縁がなさそうでした。大体os.fsyncとか使わないだろうし。fobj.flushはよくあるだろうけど。

あとはdbを使うときに間接的に影響を受けるケース。

MySQLのinnoDBの設定とか。

nnodb_flush_method

もし fdatasync (デフォルト)に設定すると、InnoDB はデータとログ ファイルの両方をフラッシュする為に fsync() を利用します。もし O_DSYNC に設定すると、InnoDB はログ ファイルをオープン、フラッシュする為に O_SYNC を利用しますが、データ ファイルをフラッシュする為には fsync() を利用します。もし O_DIRECT が指定されると(GNU/Linux バージョン上で有効)、InnoDB はデータ ファイルをオープンする為に O_DIRECT を利用し、データとログ ファイルの両方をフラッシュする為に fsync() を利用します。InnoDB は fdatasync() の代わりに fsync() を利用する事、また様々な種類の Unix 上で問題があった為、デフォルトで O_DSYNC は利用しないという事に注意してください。この変数は Unix に対してだけ関連があります。Windows 上では、フラッシュの方法は毎回 async_unbuffered で、変更する事はできません。

この変数の異なる値は InnoDB performance 上で著しい影響を持ちます。例えば、InnoDB データとログ ファイルが SAN 上に位置するいくつかのシステム上では、innodb_flush_method を O_DIRECT に設定する事は、3つの要因によってシンプルな SELECT ステートメントの性能を劣らせる可能性があるという事が発見されました。

なんか変だと思うのは気のせい?

先日読んだheystack話もメタデータがNFS上にあっておせーというのがモチベーションでしたね。

0 件のコメント: