はじめに
STATSPACKを手動でレポート出力するのは時間がかかるため、毎日、前日のレポートを自動出力する処理を作成した。
内容
前提
実行環境は以下となる。
- OSバージョン
- Windows Server 2016 Standard
- Oracle Databaseバージョン
- Oracle Database 12C
処理構成
・バッチ:1つ
⇒メイン処理
タスクスケジューラなどで、このバッチを定期的に実行する。
・VBS:1つ
⇒日付加工用処理
・SQLファイル:2つ
⇒スナップショット情報を取得する処理
⇒STATSPACKを出力する処理
メイン処理
REM STATSPACK出力処理
SET BAT_NAME=CREATE_STATSPACK.BAT
SET BAT_PATH=フォルダパスを指定する
SET WORK_PATH=%BAT_PATH%WORK\
SET REPORT_PATH=%BAT_PATH%REPORT\
REM DAY_BEFORE1.TXTが存在するか確認
IF EXIST %WORK_PATH%DAY_BEFORE1.TXT (GOTO CHECK) ELSE (GOTO ERROR)
IF ERRORLEVEL 1 GOTO ERROR
:CHECK
REM DAY_BEFORE2.TXTが存在するか確認
IF EXIST %WORK_PATH%DAY_BEFORE2.TXT (GOTO JOB) ELSE (GOTO ERROR)
IF ERRORLEVEL 1 GOTO ERROR
:JOB
REM 前日日付を取得
WSCRIPT %BAT_PATH%DAY_BEFORE.VBS
IF ERRORLEVEL 1 GOTO ERROR
REM 前日日付を変数にセット
FOR /F "USEBACKQ" %%A IN (TYPE %WORK_PATH%DAY_BEFORE1.TXT) DO SET DAY_BEFORE1=%%A
IF ERRORLEVEL 1 GOTO ERROR
REM 前日日付の"/"なしを変数にセット
FOR /F "USEBACKQ" %%B IN (TYPE %WORK_PATH%DAY_BEFORE2.TXT) DO SET DAY_BEFORE2=%%B
IF ERRORLEVEL 1 GOTO ERROR
REM 前日日付を元にSTATSPACKのスナップショットIDとIDの該当時間を取得
SQLPLUS /NOLOG @%BAT_PATH%CREATE_STATSPACK.SQL %DAY_BEFORE1%
IF ERRORLEVEL 1 GOTO ERROR
REM レポート出力
FOR /F "TOKENS=1,2,3,4" %%C IN (%WORK_PATH%CREATE_STATSPACK.TXT) DO (
SQLPLUS /NOLOG @%BAT_PATH%AUTO_SPREPORT.SQL %%C %%D %DAY_BEFORE2%_%%E_%%F
)
REM 前日日付のフォルダが既に存在する場合は削除する
RMDIR /S /Q %REPORT_PATH%%DAY_BEFORE2%
REM ファイルを格納するフォルダを作成
MKDIR %REPORT_PATH%%DAY_BEFORE2%
IF ERRORLEVEL 1 GOTO ERROR
REM STATSPACKレポートを作成したフォルダに移動する
MOVE %BAT_PATH%*.LST %REPORT_PATH%%DAY_BEFORE2%
IF ERRORLEVEL 1 GOTO ERROR
REM フォルダサイズが少し大きいため、圧縮する
POWERSHELL COMPRESS-ARCHIVE -FORCE %REPORT_PATH%%DAY_BEFORE2% %REPORT_PATH%%DAY_BEFORE2%.ZIP
IF ERRORLEVEL 1 GOTO ERROR
REM 圧縮後、不要になったフォルダを削除
RMDIR /S /Q %REPORT_PATH%%DAY_BEFORE2%
IF ERRORLEVEL 1 GOTO ERROR
REM データ保存期間は1年としているため、1年前の圧縮ファイルを削除
FORFILES /P %REPORT_PATH% /D -365 /M "*.ZIP" /C "CMD /C DEL @FILE"
:SUCCESS
ECHO 正常終了,%DATE% %TIME:~0,8% > %BAT_PATH%LOG\CREATE_STATSPACK.LOG
GOTO END
:ERROR
ECHO 異常終了,%DATE% %TIME:~0,8% > %BAT_PATH%LOG\CREATE_STATSPACK.LOG
GOTO END
:END
EXIT
日付加工用処理
strFile = "ファイルパスを指定する"
'ファイルシステムオブジェクト作成
Set objFS = CreateObject("Scripting.FileSystemObject")
' ファイルオープン
Set objText = objFS.OpenTextFile(strFile, 2)
' 書き込み※/ありの日付
objtext.Write(Date() - 1)
' ファイルクローズ
objText.Close
strFile2 = "ファイルパスを指定する"
'ファイルシステムオブジェクト作成
Set objFS2 = CreateObject("Scripting.FileSystemObject")
' ファイルオープン
Set objText2 = objFS2.OpenTextFile(strFile2, 2)
d = Date() - 1
' 書き込み※/なしの日付
objtext2.Write(Replace(d, "/", ""))
' ファイルクローズ
objText2.Close
スナップショット取得処理
WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK
CONNECT perfstat/パスワード@サービス名
SET FEEDBACK OFF
SET HEADING OFF
SET VERIFY OFF
SET PAGESIZE 0
SET LINESIZE 100
SET FEED OFF
SET TRIMS ON
SPOOL テキストを出力するパス
WITH WK AS (
SELECT SNAP_ID ,ROW_NUMBER() OVER (ORDER BY SNAP_ID) AS SEQ ,TO_CHAR(SNAP_TIME, 'HH24') AS SNAP_TIME
FROM PERFSTAT.STATS$SNAPSHOT
WHERE TO_CHAR(TO_DATE(SNAP_TIME ,'YYYY/MM/DD')) = TO_CHAR(TO_DATE( '&1' ,'YYYY/MM/DD'))
)
SELECT TRIM(A.SNAP_ID) || ' ' || TRIM(B.SNAP_ID) || ' ' || TRIM(A.SNAP_TIME) || ' ' || TRIM(B.SNAP_TIME)
FROM WK A
LEFT JOIN WK B
ON A.SEQ+1 = B.SEQ
WHERE B.SNAP_ID IS NOT NULL;
SPOOL OFF
EXIT
STATSPACK出力処理
WHENEVER OSERROR EXIT 99
WHENEVER SQLERROR EXIT 99
CONNECT perfstat/パスワード@サービス名
SET LINESIZE 300
SET PAGESIZE 0
SET TAB OFF
SET ECHO OFF
SET HEAD OFF
SET FEEDBACK OFF
SET VERIFY OFF
SET TRIMSPOOL ON
SET ARRAYSIZE 5000
SET TERM OFF
DEFINE begin_snap="&1"
DEFINE end_snap="&2"
DEFINE report_name="&3"
@?/rdbms/admin/spreport.sql
EXIT
注意点
以下、3点の注意に留意すること。
①前日以外の出力について
処理は前日のスナップショットを出力するものであるため、当日のスナップショットを基に出したいなどが発生する場合、日付を決めているVBSを修正するか、VBSをコメントアウトして、WORKファイルに直に日付を入れて対応することになる。
②DB再起動の影響について
STATSPACKの仕様で、DBを再起動した時間のスナップショットは作成されないため、DBを再起動した時間帯のレポートは出力されないので注意が必要。
③出力したレポートについて
レポートは1年間保持で、それ以降は削除されるようになっているが、使ってるサーバやPCの容量によては、レポートファイルのサイズが容量を圧迫する可能性があるため、注意が必要。
まとめ
STATSPACKは障害やパフォーマンス調査に便利だが、出力が面倒なため、自動化することをお勧めする。
コメント