スキップしてメイン コンテンツに移動

Unbreakable Enterprise Kernelのチューニングは非同期I/Oか?

小幡さん、yohei-aさん、wmo6hashさんなど、いろいろご意見がありましたが、一度、Oracleの非同期I/Oの実装はどうだったのか再確認が必要だと思いちょっと調べてみます。

手当たり次第やってもしょうがないので、以下の3つの観点で調査してみます。多分、何回かに分けて調査すると思うのですが、今回は初期化パラメータfilesystemio_options = [none|directio|asynch|setall]でどのようにI/Oに関するシステムコールが変化するか見てみます。

1. データファイルへの書き込み
    これは、DBWRが行っていますので、filesystemio_optionsの各モードでDBWRがopen|writeを
    どのように実行しているか?

2.REDOへの書き込み
    これは、LGWRが行っていますので、filesystemio_optionsの各モードでLGWRがopen|writeを
    どのように実行しているか?

3. データファイルの読み込み
    これは、shadowプロセスが行っていますので、filesystemio_optionsの各モードでshadowプロセス
    がopen|writeをどのように実行しているか?

1、2のトレースを取るには以下のような感じです。
# openのシステムコールを確認
strace -f -o /tmp/oracle.trc -e open sqlplus / as sysdba << EOF
startup
EOF

# 別ターミナルで
strace -o /tmp/oracle_dbwr.trc -p 
strace -o /tmp/oracle_lgw.trc -p 

# 別ターミナルで
sqlplus xxx/yyyy
SQL> insert into xxxx values (xxxx);
SQL> -- lgwに書き出させる
SQL> commit;
SQL> -- dbwの書き出させる
SQL> alter system flush buffer_cache;

3のトレースを取るには以下のような感じです。
strace -f -o /tmp/shadown.trc sqlplus xxx/yyy
SQL> -- direct path readとなるように
SQL> select /*+ full */ count(*) from big_table;

では、結果です。

1. DBWRの動作
   filesystemio_options=none
   オープンモード
       open("/oracle_ssd/oradata/soe_ssd.dbf", O_RDWR|O_SYNC) = 25

   書き込み
       pwrite(25, " \242\0\0\370\360\261\1\236\235\277\0\0\0\1\4\233\376\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 65536, 26812022784) = 65536

   filesystemio_options=directio
   オープンモード
       open("/oracle_ssd/oradata/soe_ssd.dbf", O_RDWR|O_SYNC|O_DIRECT) = 25


   書き込み
       pwrite(25, "\6\242\0\0\377\360\261\1\207\355\277\0\0\0\1\6\317\352\0\0\1\0\0\0\204\37\1\0{\355\277\0"..., 8192, 26812080128) = 8192

   filesystemio_options=asynch
   オープンモード
       open("/oracle_ssd/oradata/soe_ssd.dbf", O_RDWR|O_SYNC) = 25


   書き込み
       io_submit(140371209195520, 1, {{0x7faab86dfc00, 0, 1, 0, 20}}) = 1
       io_getevents(140371209195520, 1, 128, {{0x7faab86dfc00, 0x7faab86dfc00, 8192, 0}}, {600, 0}) = 1

    filesystemio_options=setall
   オープンモード
       open("/oracle_ssd/oradata/soe_ssd.dbf", O_RDWR|O_SYNC|O_DIRECT) = 25


   書き込み
       io_submit(139687490887680, 58, {{0x7f0b87a667c0, 0, 1, 0, 20}, ... {0x7f0b87a5caf8, 0, 1, 0, 25}}) = 58
       io_getevents(139687490887680, 4, 128, {{0x7f0b87a5caf8, 0x7f0b87a5caf8, 8192, 0}, ... {0x7f0b87a63718, 0x7f0b87a63718, 8192, 0}}, {600, 0}) = 4

2. LGWRの動作
   filesystemio_options=none
   オープンモード
       open("/oracle_local/oradata/redo06.log", O_RDWR|O_SYNC) = 22


   書き込み
       pwrite(22, "\1\"\0\0\246W\2\0K\0\0\0\20\2007\250\220\1\0\0\r\0\0\0\312\235\277\0\1\0\0\0"..., 512, 78597120) = 512

   filesystemio_options=directio
   オープンモード
       open("/oracle_local/oradata/redo06.log", O_RDWR|O_SYNC|O_DIRECT) = 22


   書き込み
       pwrite(22, "\1\"\0\0\312\0\0\0L\0\0\0\20\200Es\360\1\0\0\r\0\0\0\252\355\277\0\1\0\0\0"..., 512, 103424) = 512

   filesystemio_options=asynch
   オープンモード
       open("/oracle_local/oradata/redo06.log", O_RDWR|O_SYNC) = 22


   書き込み
       io_submit(140134974480384, 1, {{0x7f73b5153c50, 0, 1, 0, 21}}) = 1
       io_getevents(140134974480384, 1, 128, {{0x7f73b5153c50, 0x7f73b5153c50, 512, 0}}, {600, 0}) = 1

   filesystemio_options=setall
   オープンモード
       open("/oracle_local/oradata/redo06.log", O_RDWR|O_SYNC|O_DIRECT) = 22


   書き込み
       io_submit(139658147393536, 1, {{0x7f04aff94c50, 0, 1, 0, 22}}) = 1
       io_getevents(139658147393536, 1, 128, {{0x7f04aff94c50, 0x7f04aff94c50, 512, 0}}, {600, 0}) = 1

3. shadowプロセスの動作
   filesystemio_options=none
   オープンモード
       open("/oracle_ssd/oradata/soe_ssd.dbf", O_RDWR|O_SYNC) = 12

   読み込み
       pread(12, "#\242\0\0\203\36\240\1\353\37\276\0\0\0\1\4\n\257\0\0\0\0\0\0\0\0\0\0\353\331\240\1"..., 8192, 17243856896) = 8192

   filesystemio_options=directio
   オープンモード
       open("/oracle_ssd/oradata/soe_ssd.dbf", O_RDWR|O_SYNC|O_DIRECT) = 12


   読み込み
       pread(12, "#\242\0\0\203\36\240\1\353\37\276\0\0\0\1\4\n\257\0\0\0\0\0\0\0\0\0\0\353\331\240\1"..., 8192, 17243856896) = 8192

   filesystemio_options=asynch
   オープンモード
       open("/oracle_ssd/oradata/soe_ssd.dbf", O_RDWR|O_SYNC) = 12


   読み込み
       pread(12, "#\242\0\0\203\36\240\1\353\37\276\0\0\0\1\4\n\257\0\0\0\0\0\0\0\0\0\0\353\331\240\1"..., 8192, 17243856896) = 8192

    filesystemio_options=setall
   オープンモード
       open("/oracle_ssd/oradata/soe_ssd.dbf", O_RDWR|O_SYNC|O_DIRECT) = 12


   読み込み
       pread(12, "#\242\0\0\203\36\240\1\353\37\276\0\0\0\1\4\n\257\0\0\0\0\0\0\0\0\0\0\353\331\240\1"..., 8192, 17243856896) = 8192

ちょっと見づらいかもしれませんが。。。ただ、基本的に想定通りの動きです。

ただ1点、不思議な点があります。
私の認識ではio_submit(2)はO_DIRECTをつけてopenしないと同期I/Oとなると思っていたのですが、上記結果からfilesystemio_options=asynchの場合は、O_DIRECTフラグが付いていません。それにも関わらずio_submit(2)で非同期I/Oを行う(こと意図していると思う)動作になっています。

本当に非同期I/Oになっているのだろうか?

コメント

  1. >私の認識ではio_submit(2)はO_DIRECTをつけてopenしないと同期I/Oとなると思っていたのですが

    「詳解 Linuxカーネル 第3版」P.718の「16.4.1 Linux 2.6 における非同期I/O」に「Linux カーネル 2.6.11 では、非同期機能はまだ開発中であり、O_DIRECT フラグを指定してオープンしたファイルのみ、非同期で処理できます」と書かれていました。

    返信削除
  2. いつも、ご指摘ありがとうございます。以前、filesystemio_optionsでちょっとハマりまして、ちょっとムキになってやってしまいました。ちゃんと事前に調べていれば、良かった。。。

    返信削除
  3. 検証手順とかめちゃめちゃ勉強になりました!
    個人的には検証して頂いてうれしかったです。

    返信削除

コメントを投稿

このブログの人気の投稿

コンカレンシーにまつわるアレ・コレ

最初に 今日は、JPOUG Advent Calendarのエントリです。
昨日の小田さんに続き、私は、1μmも役には立たないエントリとなります !

最近思うこと 昨今、データベースシステムを構成するハードウェアは大量のコア、一昔では考えられないほどの大量のメモリーが搭載し、さらにデータベースのボトルネックの王者たる風格さえ漂っていたI/Oにも高速化の波が押し寄せてきています。

そんな中、古くて新しい、そして、RDBMSとしての真価を問われるコンカレンシーの問題がボトルネックとして浮かび上がっているような気がしています。

このコンカレンシーの問題は、曲者で、どんなに高速なCPUを沢山搭載しても、どんなに沢山のメモリーを積んでも、ロケットばりの高速ストレージを使っても、コンカレンシーがボトルネックとなると全くパフォーマンスがスケールしません。(まぁー、極端な言い回しですが)



そんな事を、つらつら考えつつ、コンカレンシーの問題が大きく関係するBuffer Cache上で繰り広げられる様々な動きを考えて見ることにします。

ここで、登場するボトルネックの原因となるWait Eventは、こんな物です。

latch: cache buffers chainslatch: cache buffer lru chainfree buffer waitsread by other session

まず、SELECT文のEXEC/FETCHフェーズを想像して下さい。

上記のWait Eventを噛み砕くと、こんな感じでしょうか?

latch: cache buffers chains 「僕の探しているブロックはキャッシュされていますか~」を多くの人(Session)が聞きたがっている。でも、キャッシュされているか答えをもらうためのチケット(cache buffers chains latch)は一つ(もしくは非常に少ない)なので、なかなか、その順番が回ってこない。なので、「待つ」

* ちなみに latch: cache buffers chains は"聞く"だけなら、コンカレンシーの問題は起こらないのですが、このラッチは、「ブロックをキャッシュするので、ちゃんと管理しておいて~」の場合には、他の人が触れないようにする必要がある("聞く"こともでき…

Linuxのファイルシステムで最適なものは?

Linuxでは多くのファイルシステムがあり、現在も様々なものが開発中です。

メジャーなものとしてext2、ext3がありますが、現在ext4が主流になろうとしています。また、oracleが開発したBtrfs(B-tree file system)などのような、SSDへの最適化やCOW(Copy on Write)など次世代のファイルシステムが沢山あります。

そこで、あまり最新のものは今後やるとして、昔からあるファイルシステムと今のファイルシステムでどの程度パフォーマンスに差があるのか検証してみます。

* 本当はBtrfsも検証したかったのですが、SSDが不調なのとDIRECT I/Oが未サポートだったので断念しました
Linux 2.6.35 released, with Btrfs Direct I/O support and -ENOSPC handling of volume management operations, completing the -ENOSPC support.
ext2からext3がLinuxの主流になったとき、ext3のジャーナリング機能を嫌い、Oracle構築でxfsを使う方も多かったのではないでしょうか?何せ、xfsはメタデータのみジャーナリングを行い、実データに関しては基本知らんぷりという仕様だからです。そんな中途半端?なジャーナリングを備えたファイルシステムがなぜ、好まれるのか?

答えは簡単です。Oracleにとって実データのジャーナルは必要ないからです。OracleはデータベースのファイルをO_SYNCオプションを付けて、オープンします。それは、OSのファイルキャッシュが危ないことを知っているからです。Oracleが「書いた!」と思っても、実はファイルキャッシュにしか書かれておらず、実際のファイルには「書かれていない!」こともあり得るわけです。これを確実に「書いた!」もしくは「失敗した!」とするため(白黒はっきりさせるため)にO_SYNCオプションを付けてオープンしているわけです。

とりあえず、上記のように、ファイルシステムは沢山あって、ジャーナリングなど高機能を提供するものも多い。ただ、そのような高機能が不必要な場合もあるわけで、システムによって、特性を見極めてファイルシステムを選択する必要もあるかも知れない。というわ…