小幡さん、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のトレースを取るには以下のような感じです。
3のトレースを取るには以下のような感じです。
では、結果です。
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つの観点で調査してみます。多分、何回かに分けて調査すると思うのですが、今回は初期化パラメータ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 -pstrace -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になっているのだろうか?
>私の認識では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 フラグを指定してオープンしたファイルのみ、非同期で処理できます」と書かれていました。
いつも、ご指摘ありがとうございます。以前、filesystemio_optionsでちょっとハマりまして、ちょっとムキになってやってしまいました。ちゃんと事前に調べていれば、良かった。。。
返信削除検証手順とかめちゃめちゃ勉強になりました!
返信削除個人的には検証して頂いてうれしかったです。