2010/09/30

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になっているのだろうか?

3 コメント:

yohei-a さんのコメント...

>私の認識では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 フラグを指定してオープンしたファイルのみ、非同期で処理できます」と書かれていました。

koji shinkubo さんのコメント...

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

yohei-a さんのコメント...

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

コメントを投稿