2017.10.25
Write complete waits
目次
基本情報
サーバプロセスがDBWRプロセスによってディスクに記録されているブロックを変更しようとする場合には、変更が終わるまで待たなければならず、待っている間write complete waitsイベントを待機します。
write complete waits待機は、buffer busy waits待機と同様にbuffer lock競合による待機に分類することができる。DBWRはダーティバッファをディスクに記録している間、バッファのbuffer lockを排他的に獲得します。この時、バッファを読んだり、変更したい他のプロセスは、この作業が終わるのを待って、write complete waitsイベントを待機することになります。
write complete waits待機が普遍的に表示される場合は、アプリケーションの問題というよりはDBWRのパフォーマンスの問題である可能性が非常に高くなります。サーバプロセスがディスクに書き込まれているバッファを読み取る確率が、実際には高くないのに、これによる待機を経ることはDBWRがダーティバッファを記録する時間が過度に長いことを意味します。DBWRの性能が遅い理由は、色々ありますが、ほとんどは、次のカテゴリに入ります。
パラメータと待機時間
待機パラメータ
write complete waitsイベントの待ち行列は次と等しい。
・P1 : File# ・P2 : Block# ・P3 : Reason ID
待機時間
1秒
チェック・ポイントとソリューション
低速I/Oサブシステム
free buffer waits#低速のI/Oサブシステムを参照してください。
DBWRの負荷があまりにも多い場合
頻繁にチェックポイントが発生した場合、DBWRの活動量が過度に多くなって、これにより、DBWRのパフォーマンスが低下することになります。DBWRのパフォーマンスの低下は、システムの全体的なパフォーマンスの低下に直結します。 FAST_START_MTTR_TARGET値を過度に小さくすると、頻繁に増分チェックポイント(Incremental Checkingpoint)作業が発生することになります。 REDOログ・ファイルのサイズが小さすぎる場合、頻繁にログファイルのスイッチ(log file switch)が発生することになって、これにより、チェックポイント処理が増加します。Parallel Queryによりdirect path readが発生した場合には、truncate、drop、hot backup時にもチェックポイントが発生します。もし、I/Oシステムのパフォーマンスの問題がないのに、write complete waits待機が表示される場合DBWRに余計な負荷を与える要素がないか調べる必要があります。
間接的にDBWRのパフォーマンスを向上させる方法として、複数のバッファプール(multiple buffer pool)を適切に使用することも推奨されています。システムで一般的によく使用されるオブジェクトは、Defaultバッファを使用し、それよりは程度が低いが比較的定期的に使用されるオブジェクトは、Keepバッファプールに常に常駐させます。最後に、使用頻度が少ないオブジェクトは、Recycleバッファプールを使用します。Keepバッファプールに常駐されたオブジェクトは、比較的、ディスクに記録されている頻度が低くなってこれによりwrite complete waits待機回数が減ることになります。加えて、KeepバッファプールとRecycleバッファプールは、それぞれ別のcache buffers lru chainラッチを使用するため、ラッチの競合を減少させる効果もあるのです。複数のバッファプールはDBWRの性能とは直接の関係はありませんが、バッファ・キャッシュの効率を高めることで、メモリに常駐するデータが不必要にディスクに書き込まれる頻度を下げ、これによりwrite complete waits待機が発生する確率を下げます。
オラクル8i以前はwrite complete waits待機の主犯でwrite batch sizeが挙げられました。 write batch sizeが大きいDBWRが記録される時間が長くなって、これによる待機が発生するようになるのですが、8i以降では、write batch sizeによるパフォーマンスの問題は消えました。
イベントチップ
FAST_START_MTTR_TARGETと書込み完了待ち
FAST_START_MTTR_TARGETを変更しながら余分なチェックポイントがwrite complete waits待機とパフォーマンスにどのような影響を与えるかをテストしてみましょう。テストシナリオは次のとおりです。
・64,000件のローを持つCBL_TEST1〜CBL_TEST20テーブルを生成します。 ・同時に20個のセッションでCBL_TEST1〜CBL_TEST20テーブルをそれぞれ更新します。 ・FAST_START_MTTR_TARGET値を1に与えた場合と600に与えた場合には、システムレベルで write complete waits待機がどのように発生していることを確認します。
-- ダーティバッファを作成するプロシージャ create or replace procedure wcw_update(p_idx in number) is begin for idx in 1 .. 500 loop execute immediate 'update cbl_test'||p_idx || ' set id = id where id = :id' using idx; commit; end loop; end; / var job_no number; -- 複数のセッションで同時にテーブルを更新 begin for idx in 1 .. 19 loop dbms_job.submit(:job_no, 'wcw_update('||idx||');'); commit; end loop; end; / exec wcw_update(20); SQL> select * from ( select event, total_waits, time_waited from v$system_event where wait_class <> 'Idle' order by 3 desc ) where rownum <= 100;
・FAST_START_MTTR_TARGET=1の場合
FAST_START_MTTR_TARGET=1の値を与えて、非常に頻繁にチェックポイントが発生するようにした場合、V$ SYSTEM_EVENTを通じて確認し、スタンバイ現状とV$ SYSSTATを介して確認したチェックポイント関連の統計値は、以下の通りです。
SQL> select * from ( select event, total_waits, time_waited from v$system_event where wait_class <> 'Idle' order by 3 desc ) where rownum <= 100;
EVENT TOTAL_WAITS TIME_WAITED ------------------------------ ----------- ----------- log buffer space 2440 81186 log file switch (private stran 565 31701 d flush incomplete) free buffer waits 1367 14198 write complete waits 56 5334 log file parallel write 524 4964 buffer busy waits 133 2302 log file switch completion 120 2215 db file sequential read 8589 1761 os thread startup 47 1759 ... SQL> select name, value from v$sysstat where name like '%checkpoint%; NAME VALUE -------------------------------------------------- ---------- physical writes non checkpoint 16823 DBWR checkpoint buffers written 18024 DBWR thread checkpoint buffers written 4063 DBWR tablespace checkpoint buffers written 0 DBWR parallel query checkpoint buffers written 0 DBWR checkpoints 7 background checkpoints started 4 background checkpoints completed 3
・FAST_START_MTTR_TARGET=600の場合、
FAST_START_MTTR_TARGET=600の値を与えてチェックポイントの頻度を減らした場合、V$ SYSTEM_EVENTを通じて確認し、スタンバイ現状とV$ SYSSTATを介して確認したチェックポイント関連の統計値は、以下の通りです。
SQL> select * from ( select event, total_waits, time_waited from v$system_event where wait_class <> 'Idle' order by 3 desc ) where rownum <= 100; EVENT TOTAL_WAITS TIME_WAITED ------------------------------ ----------- ----------- log buffer space 2532 77920 free buffer waits 5208 11624 log file switch (checkpoint in 93 6159 complete) log file switch completion 235 5915 log file parallel write 319 4698 os thread startup 46 1658 write complete waits 17 1623 log file sync 41 1554 latch: cache buffers chains 187 1452 ... SQL> select name, value from v$sysstat where name like '%checkpoint%; NAME VALUE -------------------------------------------------- ---------- physical writes non checkpoint 9661 DBWR checkpoint buffers written 2089 DBWR thread checkpoint buffers written 1989 DBWR tablespace checkpoint buffers written 0 DBWR parallel query checkpoint buffers written 0 DBWR checkpoints 7 background checkpoints started 4 background checkpoints completed 2
上記のテストの結果を見ると、FAST_START_MTTR_TARGET=600の場合、増分チェックポイントの回数を減らすFAST_START_MTTR_TARGET=1の場合に比べて、write complete waits待機が大幅に減少するだけでなく、その他のすべての待機現象も全体的に少なく発生すること確認することができます。V$ SYSSTATビューでチェックポイント関連の統計値を検索してみると、頻繁にチェックポイント処理が待機時間の差をインポートされたことが分かります。もしシステム全体のデータの変更が非常に多くのチェックポイントによる負荷が生じると判断した場合、増分チェックポイントの周期を増やすことが問題を解決することができます。しかし、この場合に回復(Recovery)に多くの時間がかかる場合があることに注意しましょう。