[Oracle] V$SESSION の情報を定期的に収集・記録する | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

Statspack は一定期間内における Oracle の稼働状況のサマリー情報(合計・平均値)の分析には向いていますが、瞬間的な遅延の発生を捕らえることは困難です。

瞬間的な遅延の発生を捕らえるには V$SESSION や V$SESSION_WAIT の情報が役立ちます。


ただし、これらのビューに現れる情報はその瞬間の情報であるため、後で見てもわかりません。

実際に問題が発生した瞬間に見なければ意味がありません。


となると、問題発生時点にさかのぼって分析することができるよう、あらかじめ一定間隔で情報を収集・記録しておく必要があります。

情報の収集間隔は、長すぎるとその間に発生した遅延などの情報を捉えることができませんので、おおよそ1秒~数秒程度にするのがよさそうですが、短すぎると負荷も気になりますので、そこは実際の負荷を見ながら調整したほうがよさそうです。
(V$SESSION や V$SESSION_WAIT の情報はメモリ上に保持されているためそれほど大きな負荷はかからないようですが...)


定期的に情報を収集する方法としてはいろいろな方法があると思いますが、実行間隔が短いだけに、1つの常駐セッション内で一定間隔ごとに情報の収集・記録を繰り返すのがよいように思います。
(間違っても毎回データベースへの接続と切断を繰り返すようなロジックにはすべきではないでしょう。)

また、収集した情報は、ファイルまたはテーブルのいずれかに記録することになると思いますが、個人的にはテーブルに記録したほうが後で検索・加工しやすいのでいいのではないかと思います。


以下にスクリプトの一例を示します。

BEGIN
  LOOP
    INSERT INTO HST_SESSION
      SELECT 
        SYSTIMESTAMP AS SAMPLE_TIME, 
        SID, 
        USERNAME, 
        STATUS, 
        MACHINE, 
        PROGRAM, 
        SQL_ID, 
        EVENT, 
        WAIT_CLASS, 
        STATE, 
        P1, 
        P2, 
        P3, 
        SECONDS_IN_WAIT 
        FROM V$SESSION 
        WHERE TYPE != 'BACKGROUND' 
          AND USERNAME IS NOT NULL;
    COMMIT;
    DBMS_LOCK.SLEEP(1);
  END LOOP;
END;
/

※Oacle 10g 向けです。( 9i 以前の場合、待機イベントの情報は V$SESSION_WAIT から取得しなければなりません。)

この例では、1秒ごとに V$SESSION の情報(一部)を収集し、HST_SESSION というテーブルに記録しています。


このようなスクリプトをインスタンスの起動直後に起動すればあとは勝手に情報を収集・記録してくれるわけですが、収集する情報は結構なボリュームになりますので、定期的に削除する仕組みも必要でしょう。


ちなみに、こういった仕組みは Oracle 10g からはアクティブ・セッション・ヒストリ (ASH)という機能として実装されており、デフォルトで稼動しています。

故に ASH が収集している情報を利用できれば、上記のような仕組みをわざわざ用意する必要はないのですが、残念ながら Enterprise Edition でかつ Oracle Diagnostics Pack というオプションライセンスを購入していないとこの ASH が収集している情報は利用できないようです。

同じような情報を二重に収集・記録することによってリソースを無駄に消費してしまうのが気に入らないところですが、致し方ないところです...


ただ、実際問題、V$SESSION や V$SESSION_WAIT の情報を常に収集・記録しておくべきかどうかというと、私は必ずしもそうは思いません。

システムの形態にもよりますが、普通は Statspack などで捕らえられないような問題が発生した時に、初めて仕込んでみるくらいの感覚でもいいのではないでしょうか。