今週の名言
「人にものを教えることはできない。できることは、相手のなかにすでにある力を見いだすこと、その手助けである。」
ガリレオ・ガリレイ
今回は小ネタで
前回に引き続き「Identity Column」のつもりでしたが、事情により今回は別のトリビア的なネタを紹介します。
アラートログ監視の難しさ
Oracleの運用監視において、アラートログの中の「ORA-」で始まるメッセージを通知するということは当たり前に行われていると思いますが、エラー・メッセージ・マニュアルで「処置: 処置は必要ありません。」のように説明されているアラートが真夜中にエスカレーションされた経験はないでしょうか?
Oracleにある程度詳しい人であれば、経験から「これはとりあえず様子見でよいかな。」というような判断を下すことができるかもしれませんが、24時間待機のオペレータにそこまでの判断を求めることは難しいのではないかと思います。
そこで、「このメッセージは監視対象から外す」というようなルールを決めているところは多いと思います。
私もそのような取り組みに関わったことがあるのですが、システムごとに発生するエラーの傾向が異なるので、どのシステムでも使える普遍的な「監視対象メッセージ一覧」を作るのは現実的にはかなり難しいのではないだろうかという実感を持っています。
ところでOracleエラーっていくつあるの?
いつまで経っても「監視対象メッセージ一覧」を作ることができないことに業を煮やし、Oracleエラーが一体いくつ存在しているのか気になって調べてみたことがあります。
エラー・メッセージ・マニュアルを頭から数えるのはかなり心が折れる作業になりそうなので、以下のPL/SQLスクリプトを作って調べてみました。
Oracle 11.2.0.4の場合
SQL> DECLARE 2 sql_code NUMBER; 3 str_pos NUMBER; 4 cnt NUMBER; 5 BEGIN 6 str_pos := 0; 7 cnt := 0; 8 FOR sql_code IN 1..99999 LOOP 9 str_pos := INSTR(SQLERRM(-sql_code),'not found;',1,1); 10 IF str_pos = 0 THEN 11 cnt := cnt + 1; 12 END IF; 13 END LOOP; 14 DBMS_OUTPUT.PUT_LINE('Nuber of Error Code : ' || cnt); 15 END; 16 / Nuber of Error Code : 54387 PL/SQL procedure successfully completed.
54,387個のメッセージという結果が得られました。
大訂正!!(2015.05.23)
Oracleエラーがこんなに多いはずがないとどうも腑に落ちなかったのですが、とんでもない間違いをしていたことに気付きました。
SQL> BEGIN 2 DBMS_OUTPUT.PUT_LINE(SQLERRM(-99999)); 3 END; 4 / 99999: non-ORACLE exception PL/SQL procedure successfully completed.
この「non-ORACLE exception」をカウントに入れてました。orz
これでは純粋なORA-エラーになりません。
とりあえず修正版
この不要なメッセージも除外するようにコードを書き直して実行してみたのが以下の結果です。
SQL> DECLARE 2 sql_code NUMBER; 3 cnt NUMBER :=0; 4 err_msg VARCHAR2(2000); 5 BEGIN 6 FOR sql_code IN 1..99999 LOOP 7 err_msg := SQLERRM(-sql_code); 8 IF err_msg NOT LIKE '%not found;%' AND err_msg NOT LIKE '%non-ORACLE exception%' THEN 9 cnt := cnt + 1; 10 END IF; 11 END LOOP; 12 DBMS_OUTPUT.PUT_LINE('Nuber of Error Code : ' || cnt); 13 END; 14 / Nuber of Error Code : 19923 PL/SQL procedure successfully completed.
だいぶ、数が減りました。
実は、まだ無効なメッセージを含んでいる
ところが、以下のように番号は予約されているけれどメッセージが空欄のものが相当あることがわかりました。
SQL> BEGIN 2 DBMS_OUTPUT.PUT_LINE(SQLERRM(-12428)); 3 DBMS_OUTPUT.PUT_LINE(SQLERRM(-12498)); 4 DBMS_OUTPUT.PUT_LINE(SQLERRM(-12499)); 5 END; 6 / ORA-12428: ORA-12498: ORA-12499: PL/SQL procedure successfully completed.
こんなのも一緒にカウントしてたら正確なエラーの数はわかりませんね。
結局、SQLERRM関数を使って調査することは諦めることにします。
従って、上で挙げたエラー数は間違いですので無視してください。お騒がせして申し訳ありません。
その代わりもっとよい方法があるのでそちらを別途紹介することにします。