infra検証 blog

oracle成分多めです。

Oracle Databaseから定期情報取得するスクリプトについて

この記事は、 JPOUG Advent Calendar 2022 11日目の記事です。

10日目は wmo6hash さんの記事『Oracle Database Patch Maintenance '22 - wmo6hash::blog』でした。

はじめに

みなさん、スクリプトを使ってOracle Databaseの情報取得されていますか?

パフォーマンスをモニタリングできるツールがあったり、データベースのエディションがEnterprise Editionだとできることも違うかと思います。

このようなことが必要なときは得てして上記に一切当てはまらない環境かと思います。

私が過去にやって学んだことを紹介したいと思います。

※本ブログで公開したスクリプトを利用される際は、必ず十分な動作確認を行なってください。

スクリプトを利用して不具合が発生した場合でも責任は追いかねます。

結論

スクリプトでsqlplusを用いて情報取得をする場合は以下をテンプレートとして使います。

1度の接続で、SQLを実行し続けるサンプルになります。

シェルスクリプト

  • get-dbifo.sh
#/bin/sh

LOGFILE="`date '+%Y%m%d_%H%M%S'`.log"

(
echo 'connect / as sysdba'

while true
do
  echo "@v_session.sql ${LOGFILE}"
  sleep 60
done
) | sqlplus /nolog

exit 0
  • v_session.sql
set pages 0 lines 32000 trimo on trims on echo off term off feedback off

spool &1 append

select count(*) from v$session;

spool off

PowerShell

PowerShell版はシェルの焼き直し版になります。

  • get-dbifo.ps1
& {
echo "conn / as sysdba"
echo "set feedback off"

for ($i=0; $i -lt 9999; $i++){
  echo "@v_session.sql test.log"
  echo "exec DBMS_LOCK.SLEEP(60)"
}

} | sqlplus /nolog

v_session.sqlはshell版のものをそのまま使えます。

通常の情報取得だとなぜだめか

私がはじめに作ったのは以下のようなスクリプトでした。シンプルに毎回DBへ接続して情報取得するスクリプトですね。

手軽なスクリプトで作っているため、一般的なプログラミング言語でやるようなコネクションを作って、使い回すというものではありませんね。

  • get-dbinfo.sh
#/bin/sh

LOGFILE="dbinfo_`date '+%Y%m%d_%H%M%S'`.log"

while true
do
  sqlplus / as sysdba @v_session.sql ${LOGFILE} > /dev/null 2>&1  
  sleep 60
done
  • v_session.sql
set pages 0 lines 32000 trimo on trims on echo off term off feedback off

spool &1 append

select count(*) from v$session;

spool off

exit

上記で何が問題あるかというと、負荷をかけないと再現しないような障害の調査をしなければいけないときです。

このようなときはデータベースの最大接続上限に張り付くような状態が考えられるため、そもそもDBへ接続できないため情報取得できないなんてことになります。

帰宅前にスクリプト仕掛けて翌朝ログを確認したら、実際に負荷のかかった深夜の情報が取れていなかったなんてとても悲しいですよね。

PowerShell版を作る上での課題など

ブログにする上で、shellだけではと思いPowerShell版を作りましたが、思ったようにうまくいきませんでした。

パイプラインの制限

他の方のブログ(*1)でも記載がありますが、shellでのパイプと動作が違うため以下の改良をしています。

  • 無限ループをやめ、必要な分の有限ループにする。

無限ループにすると、スクリプトブロックでの出力が確定しないため、sqlplusでの処理がいつまで経っても始まりません。

  • PowerShellのStart-Sleepコマンドレットの代わりにDBMS_LOCK.SLEEPを利用する。

スクリプトブロック内でのSleepはSleepの時間分、SQLの出力を遅くするだけで出力が終わるとSQLが一気に実行されて終わります。リソースの推移なんか見れません。

まとめ

情報収集などは、パフォーマンスをモニタリングできるツール/監視ツールなど行うことがほとんどかと思います。

いざ定期的に情報収集が必要になったら、ぜひお使いになってください。

*1 PowerShell で 外部コマンドをパイプで渡す時の問題について - tech.guitarrapc.cóm