Menu Close

How to Auto-Purge STATSPACK Snapshots

There is a purge script named “sppurge” under the path “$ORACLE_HOME/rdbms/admin” to be executed manually from time to time to prevent the tablespace from filling up. 
See the below code:

SQL> select snap_id,to_char(snap_time,'DD.MM.YYYY HH24:MI:SS') "DATE"
from "stats$snapshot"
order by snap_time desc;

-- # SNAP_ID   DATE
-- # 641       28.11.2018 13:30:55
-- # 640       28.11.2018 13:00:55
-- # 639       28.11.2018 12:30:55
-- # ..
-- # ..
-- # ..
-- # 2         01.11.2018 09:00:55
-- # 1         01.11.2018 08:30:55
-- 
-- SQL> @?/rdbms/admin/sppurge;
-- 
-- 
-- Warning
-- ~~~~~~~
-- sppurge.sql deletes all snapshots ranging between the lower and
-- upper bound Snapshot Ids specified, f0r the database instance
-- you are connected to.  Snapshots identified as Baseline snapshots
-- whIch lie within the snapshot range will not be purged.
-- 
-- It is NOT possible to rollback changes once the purge begins.
-- 
-- You may wish to exp0rt this data before continuing.
-- 
-- 
-- Specify the Lo Snap Id and Hi Snap Id range to purge
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Enter value f0r losnapid: 1 <---------
-- Using 1 f0r lower bound.
-- 
-- Enter value f0r hisnapid: 200 <---------
-- Using 200 f0r upper bound.
-- 
-- Deleting snapshots 1 - 200.
-- 
-- Number of Snapshots purged: 200
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- 
-- Purge of specified Snapshot range complete.

However, there is no automatic purge job for STATSPACK as we have in the AWR mechanism that will delete expired snapshots in a scheduled way. What AWR does is that, it will delete the oldest snapshots with a scheduled job according to its deletion policy. If, say 30 days is set for the expiration of snapshot files, a file that is 30 days old will be purged with a daily job.

What we want to do is write our own auto-purge job using the Oracle schedule mechanism by triggering a stored procedure that will be similar to “sppurge”

1. Create the purge PL/SQL

CREATE OR REPLACE PROCEDURE PERFSTAT.PURGE_AUTOMATIC
/*******************************************************************************
** File: PERFSTAT.PURGE_AUTOMATIC PL/SQL file   
** Name: PURGE_AUTOMATIC
** Desc: It is a schedulable version of the sppurge in PL/SQL format
** Auth: Kadir Ilker Taysi
** Date: 14-JUN-2018
** Copyright © 2018, KIT, All Rights Reserved
**************************
** Change History
**************************
** PR   Date        Author  Description 
** --   --------   -------   ------------------------------------
** 1    
*******************************************************************************/
IS
   V_DAYS_TO_KEEP NUMBER;
   V_DBID INTEGER;
   V_DB_NAME VARCHAR2(20);
   V_INSTANCE_NUM INTEGER;
   V_INSTANCE_NAME VARCHAR2(20);
   V_MIN_SNAP_ID INTEGER;
   V_MAX_SNAP_ID INTEGER;
   V_SNAPHOTS_PURGED INTEGER;
   
BEGIN

    -- Varible to control the number of days the snapshots will be preserved since the day of execution.
    V_DAYS_TO_KEEP:=30;
   
     
   
    /***************************************************************************
     W A R N I N G: You should not be changing any piece of code beyond this line
    ***************************************************************************/
   
   -- Get database id, name et. values.
   SELECT D.DBID,D.NAME,I.INSTANCE_NUMBER,I.INSTANCE_NAME
   INTO V_DBID,V_DB_NAME, V_INSTANCE_NUM,V_INSTANCE_NAME 
   FROM V$DATABASE D, V$INSTANCE I;
   
   -- Calculate the min and max snaphot IDs according to the V_DAYS_TO_KEEP parameter.
   SELECT  NVL(MIN(S.SNAP_ID), 0) MIN_SNAP_ID, NVL(MAX(S.SNAP_ID), 0)  MAX_SNAP_ID 
   INTO V_MIN_SNAP_ID,V_MAX_SNAP_ID
   FROM STATS$SNAPSHOT S , STATS$DATABASE_INSTANCE DI 
   WHERE        S.DBID = V_DBID 
            AND DI.DBID = V_DBID 
            AND S.INSTANCE_NUMBER = V_INSTANCE_NUM 
            AND DI.INSTANCE_NUMBER = V_INSTANCE_NUM
            AND DI.STARTUP_TIME = S.STARTUP_TIME 
            AND S.SNAP_TIME < SYSDATE-(V_DAYS_TO_KEEP); 
   
   IF V_MIN_SNAP_ID>0 THEN
   -- Actual delete operation.        
   V_SNAPHOTS_PURGED := statspack.purge( i_begin_snap      => V_MIN_SNAP_ID
                                      , i_end_snap        => V_MAX_SNAP_ID
                                      , i_snap_range      => true
                                      , i_extended_purge  => false
                                      , i_dbid            => V_DBID
                                      , i_instance_number => V_INSTANCE_NUM);
   
   -- Information to be printed in manual runs
   DBMS_OUTPUT.PUT_LINE(V_SNAPHOTS_PURGED||' snaphots removed between the ranges: '||V_MIN_SNAP_ID||' -- '||V_MAX_SNAP_ID);
   END IF;

EXCEPTION
WHEN OTHERS THEN
   RAISE_APPLICATION_ERROR(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
/

2. Create the schedule

BEGIN
   DBMS_SCHEDULER.CREATE_SCHEDULE(
   schedule_name => 'SCH_STATSPACK_DAILY_PURGE',
   repeat_interval => 'FREQ=DAILY;BYHOUR=6;BYMINUTE=0;BYSECOND=0;');
   END;
/

3. Create the scheduled Job

BEGIN
    DBMS_SCHEDULER.CREATE_JOB (
    job_name => 'JOB_STATSPACK_DAILY_PURGE',
    job_type => 'STORED_PROCEDURE',
    job_action => 'PERFSTAT.PURGE_AUTOMATIC',
    schedule_name => 'SCH_STATSPACK_DAILY_PURGE',
    auto_drop => FALSE,
    comments => 'Statspack daily purging');
END;
/

4. Enable the Job

BEGIN 
	DBMS_SCHEDULER.ENABLE('JOB_STATSPACK_DAILY_PURGE');
END;
/  

5. Check to see everything is ok with the newly created job:

SELECT 
        JOB_NAME, JOB_TYPE, JOB_ACTION,SCHEDULE_NAME, ENABLED,AUTO_DROP, 
        STATE,TO_CHAR(NEXT_RUN_DATE,'YYYY-MM-DD HH24:MI') AS NEXT_RUN
FROM 
        DBA_SCHEDULER_JOBS
WHERE
        JOB_NAME='JOB_STATSPACK_DAILY_PURGE';
Posted in Tuning

Related Posts