vendredi 21 octobre 2011

RMAN Backup Reports



1] Is an RMAN Catalog really needed ?

I got a phone call from a former colleague about the why should we have an RMAN Catalog ?
Since Controlfile and RMAN Catalog Information are Synchronized,
what are the advantages of having a Catalog vs. Target Controlfile ?

-       Backup Information are kept longer than in Controlfile - however, backup information retention in Controlfile may be tuned ( control_file_record_keep_time ).
-       Easy reporting of backup status for all the Databases with a single SQL
-       RMAN scripts may be stored in Catalog ( I’ve never used that feature )
-       When backuping a Physical Standby DB or Mirrored DB ( FlashCopy - Snapshot ) – only RCatalog will keep the Backup information that Primary DB Controlfile may get when synchronizing with it ; Standby or Mirrored DB Controlfile can’t record those backups information
-       TSPITR Limitations , see below.

Reasons NOT to have a Catalog are :

-       It is possible to restore from « scratch » a database WITHOUT an RMAN Catalog ; since 9i, the « Controlfile Autobackup » feature alllows Spfile & Controlfile restore without any data about the backups – RMAN retrieves those backups with a standard named format ( %F )
-       The Catalog may be considered as a SPOF because if it’s not there, backup will fail
-       The Catalog DB should always be at the highest Oracle version ( minor number included = the fourth numbers ) of all Backuped DB and therefore should be upgraded first.

Conclusion :
Disavantages of having an RCAT seem to me more important than PROs, thus
I would recommend NOT TO HAVE an RMAN Catalog if there are no backups on Standby or Mirrored DB.
Update : for very big IT, with a lot of DBs under RMAN, I’ll provide the Reports scripts on Catalog.

** UPDATE 2 **
I found a bug when not using a Catalog : my Incremental ( Cumulative ) Backups were never removed using the command :
delete force noprompt obsolete recovery window of 7 days ;

Therefore I had to install RMAN Catalog.

Read also :
Limitations of TSPITR Without a Recovery Catalog
====================================
The undo segments at the time of the TSPITR must be part of the auxiliary set. Because RMAN has no historical record of the undo in the control file, RMAN assumes that the current rollback or undo segments were the same segments present at the time to which recovery is performed. If the undo segments have changed since that time, then TSPITR will fail.
TSPITR to a time that is too old may not succeed if Oracle has reused the control file records for needed backups. (In planning your database, set the CONTROL_FILE_RECORD_KEEP_TIME initialization parameter to a value large enough to ensure that control file records needed for TSPITR are kept.)
When not using a recovery catalog, the current control file has no record of the older incarnation of the recovered tablespace. Thus, recovery with a current control file that involves this tablespace can no longer use a backup taken prior to time t. You can, however, perform incomplete recovery of the whole database to any time less than or equal to t, if you can restore a backup control file from before time t.


2] Backup Reports from Controlfile

2.1 Report Status

Since I choose not to have a Catalog, I’ll query directly the Controlfile to find out what happened. There is a new 10g view v$rman_backup_job_details , very useful but with many bugs :
even in 10.2.0.5, columns input_bytes_display & input_bytes_display are equal , controlfile_autobackup is always ‘NO’ , Backup type DB FULL doesn’t appear.
Hence, I’m looking for the right information in another view v$backup_set_details which provides real Backup Type between DB FULL , DB INCR , ARCHIVELOG or CONTROLFILE ( that one I don’t keep because my backups always uses « controlfile autobackup » feature ).


$ cat rman_backup_report.sql

set echo off;
set serveroutput on size 1000000
set flush on;
set lines 150 pages 5000
alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';

variable a number
begin
:a:=&1;
end;
/

with rman_rep as (
select Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,Media,max(Dec_Type) Type,status,Elapsed,output_MB_per_sec,compression
 from (
select distinct to_char(a.start_time,'DD/MM/YYYY HH24:MI:SS') Start_At, to_char(a.end_time,'DD/MM/YYYY HH24:MI:SS') End_At,
ceil(a.input_bytes/1024/1024/1024) DB_ARCs_Sz_GB, ceil(a.output_bytes/1024/1024/1024) Backup_Sz_GB,
ceil(a.compression_ratio) compression, ceil(a.output_bytes_per_sec/1024/1024) output_MB_per_sec, a.output_device_type Media , -- a.input_type ,
decode(b.backup_type,'I','DB INCR',decode(b.backup_type,'L','Archlog',decode(b.backup_type,'D',decode(controlfile_included,'NO','DB FULL','CTL')))) Dec_Type,
a.status , a.time_taken_display Elapsed -- , b.controlfile_included, b.compressed
from v$rman_backup_job_details a , v$backup_set_details b
where a.session_key = b.session_key and a.session_recid = b.session_recid
and a.start_time > sysdate-:a
) where Dec_Type != 'CTL'
group by Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,compression,output_MB_per_sec,Media,status,Elapsed
)
select instance_name Instance,Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,Media,Type,r.status,Elapsed,output_MB_per_sec,compression from rman_rep r , v$instance
union
select instance_name Instance,'No Backup Found',null,null,null,null,null,null,null,null,null from dual , v$instance where not exists ( select '1' from rman_rep )
order by Start_At desc ;


exit


Call it with a loop on all the databases and HTML output with sqlplus, then we have this great report :


EMAIL_HEAD="To: ${dest_list} \nFrom: \"DBA MONITORING \"\nSubject: ${msg_sub} \nMIME-Version: 1.0\nContent-Type: Multipart/Mixed; boundary=Message-Boundary-$boundary\n\n--Message-Boundary-$boundary\nContent-Type: text/html; charset=us-ascii\nContent-Transfer-Encoding: 7bit \n\n";
echo $EMAIL_HEAD>${bup_gen}

# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
# 1. RMAN backup report
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

for BDc in ${db_1} ; do
sqlplus -s -MARKUP "HTML ON" system/${system_psw}@${BDc} @${REP_SCRIPTS}/rman_backup_report.sql ${wind} | sed -e "/<br>/d" -e 's/td {font:10pt/td {text-align:center;font:10pt/g' -e 's/font:10pt/font:9pt/g'  | egrep -iv "USER|Session|^old|^new|procedure|rows|selected" >> ${bup_gen}
if (( $? != 0 )); then return 1 ; fi
done

# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
# 2. Mail
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

sendmail -t ${dest_list} < ${bup_gen}


Execution


$ ./report_rman_bup_all.ksh 1

** [Oracle] RMAN Backup Report past 1 day(s) 19/10/11 **

** INST1 **
** INST3 **
** INFDE **
** PPRQU **
** DEVUN **
** DEVQU **
** DEVBI **

 ** end of script **


Mailed Output ( still received in Notes ! )
[Oracle] 07/05/12 RMAN Backup Report past 1 day(s)

INSTANCE
START_AT
END_AT
DB_ARCS_SZ_GB
BACKUP_SZ_GB
MEDIA
TYPE
STATUS
ELAPSED
OUTPUT_MB_PER_SEC
COMPRESSION
INST1
06/05/2012 08:00:17
06/05/2012 09:09:48
391
48
DISK
DB FULL
COMPLETED
01:09:31
12
9
INST2
06/05/2012 09:10:01
06/05/2012 09:15:37
34
6
DISK
DB FULL
COMPLETED
00:05:36
16
7

[Oracle] 16/05/12 RMAN Backup Report past 1 day(s)

INSTANCE
START_AT
END_AT
DB_ARCS_SZ_GB
BACKUP_SZ_GB
MEDIA
TYPE
STATUS
ELAPSED
OUTPUT_MB_PER_SEC
COMPRESSION
INST1
15/05/2012 22:00:28
15/05/2012 22:33:06
432
4
DISK
DB INCR
COMPLETED
00:32:38
3
111
INST2
15/05/2012 22:33:16
15/05/2012 22:35:23
34
1
DISK
DB INCR
COMPLETED
00:02:07
4
84

2.2 DB Backup Status for Monitoring Purpose

This Sql may be plugged into Nagios tool to warn for Failed Backup. Run at DB level.
Did I have a valid backup in the previous 24 Hours  sysdate-1 ?


-- last 24 hours failed backup status
select decode(count(Bstatus),0,'FAILED','OK') NagiosStatus from (
with rman_rep as (
select Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,Media,max(Dec_Type) Type,status,Elapsed,output_MB_per_sec,compression
 from (
select distinct to_char(a.start_time,'DD/MM/YYYY HH24:MI:SS') Start_At, to_char(a.end_time,'DD/MM/YYYY HH24:MI:SS') End_At,
ceil(a.input_bytes/1024/1024/1024) DB_ARCs_Sz_GB, ceil(a.output_bytes/1024/1024/1024) Backup_Sz_GB,
ceil(a.compression_ratio) compression, ceil(a.output_bytes_per_sec/1024/1024) output_MB_per_sec, a.output_device_type Media , -- a.input_type ,
decode(b.backup_type,'I','DB INCR',decode(b.backup_type,'L','Archlog',decode(b.backup_type,'D',decode(controlfile_included,'NO','DB FULL','CTL')))) Dec_Type,
a.status , a.time_taken_display Elapsed -- , b.controlfile_included, b.compressed
from v$rman_backup_job_details a , v$backup_set_details b
where a.session_key = b.session_key and a.session_recid = b.session_recid
and a.start_time > sysdate-1
) where Dec_Type like 'DB%'
group by Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,compression,output_MB_per_sec,Media,status,Elapsed
)
select r.status Bstatus from rman_rep r , v$instance
union
select 'No Backup Found' Bstatus from dual , v$instance where not exists ( select '1' from rman_rep )
) where Bstatus = 'COMPLETED'
;


Run it in a loop / sql

$ for BDc in DB1 DB2 … ; do
echo "** ${BDc} **"
sqlplus -s ina_svc/<psw>@${BDc} << !
set head off
@rman_backup_nagios.sql
!
done

** DB1 **

OK

** DB2 **

OK





3] Backup Reports from Catalog

3.1 Query to get Backup status in the Past

Reminder : DB FULL or INCRemental Backup Report includes also the Archivelogs taken during the Backup.
Type Description : DB FULL : RMAN FULL Backup previous strategy
Status is COMPLETED , FAILED or RUNNING.

Connected to the RMAN Catalog : looking back for Backups in the past Day a.start_time > sysdate-1


with rman_rep as
(
select DB_NAME,DB_KEY,Start_At,End_At,DB_ARCs_Read_Sz_GB,Backup_Sz_GB,compression,Type,output_MB_per_sec,status,Elapsed
from (
select a.db_name,a.db_key,to_char(a.start_time,'DD/MM/YYYY HH24:MI:SS') Start_At, to_char(end_time,'DD/MM/YYYY HH24:MI:SS') End_At,
ceil(input_bytes/1024/1024/1024) DB_ARCs_Read_Sz_GB, ceil(a.output_bytes/1024/1024/1024) Backup_Sz_GB,
ceil(a.compression_ratio) compression, ceil(output_bytes_per_sec/1024/1024) output_MB_per_sec,
decode(a.input_type,'DB INCR',decode(b.incremental_level,'0','DB FULL_0','DB INCR_'||b.incremental_level),a.input_type) Type,
a.status , a.time_taken_display Elapsed
from rc_rman_backup_job_details a , rc_backup_set_details b
where a.session_key = b.session_key and a.session_recid = b.session_recid and a.db_key = b.db_key
and a.start_time > sysdate-:a )
)
, rman_rep_run as
(
select DB_NAME,DB_KEY,Start_At,End_At,DB_ARCs_Read_Sz_GB,Backup_Sz_GB,compression,Type,output_MB_per_sec,status,Elapsed
from (
select a.db_name,a.db_key,to_char(a.start_time,'DD/MM/YYYY HH24:MI:SS') Start_At, to_char(end_time,'DD/MM/YYYY HH24:MI:SS') End_At,
ceil(input_bytes/1024/1024/1024) DB_ARCs_Read_Sz_GB, ceil(a.output_bytes/1024/1024/1024) Backup_Sz_GB,
ceil(a.compression_ratio) compression, ceil(output_bytes_per_sec/1024/1024) output_MB_per_sec,
a.input_type Type, a.status , a.time_taken_display Elapsed
from rc_rman_backup_job_details a
where a.start_time > sysdate-:a and a.status = 'RUNNING' )
)
select name,Start_At,End_At,DB_ARCs_Read_Sz_GB,Backup_Sz_GB,' '||Type Type,status,Elapsed,output_MB_per_sec,compression from rman_rep a , rc_database b
where a.db_key = b.db_key and Type not like '%\_' escape '\'
union -- when running, incremental_level is null
select name,Start_At,null,null,null,null,status,null,null,null from rman_rep_run a , rc_database b
where a.db_key = b.db_key
union
select name,'No Backup Found',null,null,null,null,null,null,null,null from dual , rc_database a
where not exists ( select '1' from rman_rep b where a.db_key = b.db_key )
order by name, Start_At desc ;


Run SQLPLUS Connected to the RMAN Catalog :
argument: Number of Days to look back for Backups

Query Catalog One Day in the past

$ sqlplus -s rman/rman@RCAT @rman_backup_report_cat_n_days.sql 1

NAME      START_AT            END_AT              DB_ARCS_READ_SZ_GBBACKUP_SZ_GBTYPE           STATUS    ELAPSED   OUTPUT_MB_PER_SECCOMPRESSION

DB1       25/01/2013 09:21:13                                                                  RUNNING
DB2       22/01/2013 23:00:55 22/01/2013 23:43:13                 29          25 DB INCR_1     COMPLETED 00:42:18                 10          2
DB2       22/01/2013 18:02:53 22/01/2013 21:58:55                250         148 DB FULL       COMPLETED 03:56:02                 11          2
DB3       No Backup Found
DB4   23/01/2013 16:21:45 23/01/2013 16:23:26                  1           1 ARCHIVELOG    COMPLETED 00:01:41                  1          1
DB4   23/01/2013 00:01:07 23/01/2013 01:48:22                141           3 DB FULL       COMPLETED 01:47:15                  1         48
DB4   22/01/2013 21:00:38 22/01/2013 21:15:35                  1           1 DB INCR_1     COMPLETED 00:14:57                  1          2

$

Query Catalog 5 Days in the past

$ sqlplus -s rman/rman@rmaopeo02 @rman_backup_report_cat_n_days.sql 5

NAME      START_AT            END_AT              DB_ARCS_READ_SZ_GBBACKUP_SZ_GBTYPE           STATUS    ELAPSED   OUTPUT_MB_PER_SECCOMPRESSION
-----------------------------------------------------------------------------------------------------------------------------------------------
DB_1       21/01/2013 23:01:05 21/01/2013 23:54:00                 36          35 DB INCR_1     COMPLETED 00:52:55                 12          2
DB_1       21/01/2013 18:03:55 21/01/2013 20:40:34                200          97 DB FULL       COMPLETED 02:36:39                 11          3
DB_1       20/01/2013 18:03:20 20/01/2013 20:21:34                199          97 DB FULL       COMPLETED 02:18:14                 12          3
DB_1       20/01/2013 11:01:06 20/01/2013 12:30:24                200          97 DB FULL_0     COMPLETED 01:29:18                 19          3
DB_1       19/01/2013 18:03:37 19/01/2013 20:43:02                199          97 DB FULL       COMPLETED 02:39:25                 11          3
DB_1       18/01/2013 23:00:49 18/01/2013 23:29:47                 14          14 DB INCR_1     COMPLETED 00:28:58                  8          2
DB_1       18/01/2013 18:03:59 18/01/2013 20:53:38                231         129 DB FULL       COMPLETED 02:49:39                 13          2
DB_1       17/01/2013 23:00:50 17/01/2013 23:24:11                  1           1 DB INCR_1     COMPLETED 00:23:21                  1          3
DB_1       17/01/2013 18:08:06 17/01/2013 20:47:12                199          97 DB FULL       COMPLETED 02:39:06                 11          3
DB_1       17/01/2013 15:03:16 17/01/2013 15:19:17                  1           1 DB INCR_1     COMPLETED 00:16:01                  1          3


3.2 Same Query, ready to run

$ cat rman_backup_report_cat_n_days.sql
-- RMAN Backup report Status
-- From RMAN Catalog
-- 01/17/13 vers 1.0 AUC
-- argument: Number of Days to look back for Backups

set serveroutput on size 1000000
SET VERIFY OFF ECHO OFF NEWP 0 SPA 0 PAGES 5000 FEED OFF TRIMS ON TAB OFF lines 300
alter session set nls_date_format='MM/DD/YYYY HH24:MI:SS';

variable a number
begin
:a:=&1;
end;
/

col name for a10
col Type for a15
col status for a10
col Elapsed for a10
col Start_At for a20
col End_At for a20

with rman_rep as
(
select DB_NAME,DB_KEY,Start_At,End_At,DB_ARCs_Read_Sz_GB,Backup_Sz_GB,compression,Type,output_MB_per_sec,status,Elapsed
from (
select a.db_name,a.db_key,to_char(a.start_time,'DD/MM/YYYY HH24:MI:SS') Start_At, to_char(end_time,'DD/MM/YYYY HH24:MI:SS') End_At,
ceil(input_bytes/1024/1024/1024) DB_ARCs_Read_Sz_GB, ceil(a.output_bytes/1024/1024/1024) Backup_Sz_GB,
ceil(a.compression_ratio) compression, ceil(output_bytes_per_sec/1024/1024) output_MB_per_sec,
decode(a.input_type,'DB INCR',decode(b.incremental_level,'0','DB FULL_0','DB INCR_'||b.incremental_level),a.input_type) Type,
a.status , a.time_taken_display Elapsed
from rc_rman_backup_job_details a , rc_backup_set_details b
where a.session_key = b.session_key and a.session_recid = b.session_recid and a.db_key = b.db_key
and a.start_time > sysdate-:a )
)
, rman_rep_run as
(
select DB_NAME,DB_KEY,Start_At,End_At,DB_ARCs_Read_Sz_GB,Backup_Sz_GB,compression,Type,output_MB_per_sec,status,Elapsed
from (
select a.db_name,a.db_key,to_char(a.start_time,'DD/MM/YYYY HH24:MI:SS') Start_At, to_char(end_time,'DD/MM/YYYY HH24:MI:SS') End_At,
ceil(input_bytes/1024/1024/1024) DB_ARCs_Read_Sz_GB, ceil(a.output_bytes/1024/1024/1024) Backup_Sz_GB,
ceil(a.compression_ratio) compression, ceil(output_bytes_per_sec/1024/1024) output_MB_per_sec,
a.input_type Type, a.status , a.time_taken_display Elapsed
from rc_rman_backup_job_details a
where a.start_time > sysdate-:a and a.status = 'RUNNING' )
)
select name,Start_At,End_At,DB_ARCs_Read_Sz_GB,Backup_Sz_GB,' '||Type Type,status,Elapsed,output_MB_per_sec,compression from rman_rep a , rc_database b
where a.db_key = b.db_key and Type not like '%\_' escape '\'
union -- when running, incremental_level is null
select name,Start_At,null,null,null,null,status,null,null,null from rman_rep_run a , rc_database b
where a.db_key = b.db_key
union
select name,'No Backup Found',null,null,null,null,null,null,null,null from dual , rc_database a
where not exists ( select '1' from rman_rep b where a.db_key = b.db_key )
order by name, Start_At desc ;

exit


4] Collect Data before going for Incremental Backups

At a Client, I had to show the Return On Investment of going from a FULL RMAN Backup to an Incremental strategy.
Therefore, I wrote this SQL to collect information from 9i and 10g+ DBs.

4.1 Overall DBs : Last FULL Backup Report

9i SQL

with
dbf_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) dbf_GB from dba_data_files ) ,
seg_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) seg_GB from dba_segments ) ,
tmp_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) tmp_GB from dba_temp_files )
select a.name DB , null OS , log_mode , database_role , host_name , b.version , value compatible , dbf_sz.dbf_GB , seg_sz.seg_GB , tmp_sz.tmp_GB
from v$database a , v$instance b , v$parameter c , dbf_sz , seg_sz , tmp_sz
where c.name like 'compatible'

10g+ SQL

-- 10g+
with
dbf_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) dbf_GB from dba_data_files ) ,
seg_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) seg_GB from dba_segments ) ,
tmp_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) tmp_GB from dba_temp_files )
/* 10g+ */
, rman_rep as (
select Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,Media,max(Dec_Type) Type,status,Elapsed,output_MB_per_sec,compression,compressed,BCT
 from (
select distinct to_char(a.start_time,'DD/MM/YYYY HH24:MI:SS') Start_At, to_char(a.end_time,'DD/MM/YYYY HH24:MI:SS') End_At,
ceil(a.input_bytes/1024/1024/1024) DB_ARCs_Sz_GB, ceil(a.output_bytes/1024/1024/1024) Backup_Sz_GB,
ceil(a.compression_ratio) compression, ceil(a.output_bytes_per_sec/1024/1024) output_MB_per_sec, a.output_device_type Media , -- a.input_type ,
decode(b.backup_type,'I','DB INCR',decode(b.backup_type,'L','Archlog',decode(b.backup_type,'D',decode(controlfile_included,'NO','DB FULL','CTL')))) Dec_Type,
a.status , a.time_taken_display Elapsed -- , b.controlfile_included
, b.compressed , c.status BCT
from v$rman_backup_job_details a , v$backup_set_details b , v$block_change_tracking c
where a.session_key = b.session_key and a.session_recid = b.session_recid
order by Start_At desc
) where Dec_Type != 'CTL' and Dec_Type = 'DB FULL' and rownum < 2
group by Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,compression,output_MB_per_sec,Media,status,Elapsed,compressed,BCT
) /* 10g+ end */
select a.name DB , platform_name OS , log_mode , database_role , host_name , b.version , value compatible , dbf_sz.dbf_GB , seg_sz.seg_GB , tmp_sz.tmp_GB
/* 10g+ */ , Media RMAN_Media,r.Type,r.status,Elapsed,to_char(DB_ARCs_Sz_GB) DB_ARCs_Sz_GB,Backup_Sz_GB,compressed,BCT /* 10g+ end */
from v$database a , v$instance b , v$parameter c , dbf_sz , seg_sz , tmp_sz /* 10g+ */ , rman_rep r /* 10g+ end */
where c.name like 'compatible'
/* 10g+ */
union
select a.name DB , platform_name OS , log_mode , database_role , host_name , version , value compatible , dbf_sz.dbf_GB , seg_sz.seg_GB , tmp_sz.tmp_GB
, 'No Backup Found',null,null,null,null,null,null,null
from v$database a , v$instance , v$parameter c , dbf_sz , seg_sz , tmp_sz , dual
where not exists ( select '1' from rman_rep ) and c.name like 'compatible' /* 10g+ end */

Since I query new 10g+ RMAN Views, I needed a dynamic SQL generated accordingly to the BD version.
On those views, I only need the last FULL backup data.


-- cat rman_audit_backup.sql
set serveroutput on
SET ECHO OFF NEWP 0 SPA 0 PAGES 0 FEED OFF HEAD OFF TRIMS ON TAB OFF lines 300

declare
v_vers varchar2(16) ;
v_res varchar2(256) ;
sCall varchar2(3096);
ct integer;
ig number;

begin
        dbms_output.disable;        -- *** Line added ***
        dbms_output.enable(100000); -- *** Line added ***

select substr(version,1,1) into v_vers from v$instance ;
-- dbms_output.put_line ('Oracle Version: '|| v_vers);

 case when v_vers = '9' or v_vers = '8' then -- 9i version
begin
-- 9i+
sCall :='with '
||'dbf_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) dbf_GB from dba_data_files ) , '
||'seg_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) seg_GB from dba_segments ) , '
||'tmp_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) tmp_GB from dba_temp_files ) '
||'select ''''||a.name||'';''||null||'';''||log_mode||'';''||database_role||'';''||host_name||'';''||b.version||'';''||value||'';''||dbf_sz.dbf_GB||'';''||seg_sz.seg_GB||'';''||tmp_sz.tmp_GB||'' '' '
||'from v$database a , v$instance b , v$parameter c , dbf_sz , seg_sz , tmp_sz '
||'where c.name like ''compatible'' ' ;

-- sCall :='select sysdate from dual' ;
-- dbms_output.put_line (sCall);
EXECUTE IMMEDIATE sCall INTO v_res ;

dbms_output.put_line (v_res);

end ;

 else -- 10g+ version
begin

sCall :='with '
||'dbf_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) dbf_GB from dba_data_files ) , '
||'seg_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) seg_GB from dba_segments ) , '
||'tmp_sz as ( select to_char(ceil(sum(bytes)/1024/1024/1024)) tmp_GB from dba_temp_files ), '
||'rman_rep as ( '
||'select Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,Media,max(Dec_Type) Type,status,Elapsed,output_MB_per_sec,compression,compressed,BCT '
||' from ( '
||'select distinct to_char(a.start_time,''DD/MM/YYYY HH24:MI:SS'') Start_At, to_char(a.end_time,''DD/MM/YYYY HH24:MI:SS'') End_At, '
||'ceil(a.input_bytes/1024/1024/1024) DB_ARCs_Sz_GB, ceil(a.output_bytes/1024/1024/1024) Backup_Sz_GB, '
||'ceil(a.compression_ratio) compression, ceil(a.output_bytes_per_sec/1024/1024) output_MB_per_sec, a.output_device_type Media , '
||'decode(b.backup_type,''I'',''DB INCR'',decode(b.backup_type,''L'',''Archlog'',decode(b.backup_type,''D'',decode(controlfile_included,''NO'',''DB FULL'',''CTL'')))) Dec_Type, '
||'a.status , a.time_taken_display Elapsed '
||', b.compressed , decode(c.status,''ENABLED'',''YES'',''DISABLED'',''NO'') BCT '
||'from v$rman_backup_job_details a , v$backup_set_details b , v$block_change_tracking c '
||'where a.session_key = b.session_key and a.session_recid = b.session_recid '
||'order by Start_At desc '
||') where Dec_Type != ''CTL'' and Dec_Type = ''DB FULL'' and rownum < 2 '
||'group by Start_At,End_At,DB_ARCs_Sz_GB,Backup_Sz_GB,compression,output_MB_per_sec,Media,status,Elapsed,compressed,BCT '
||') '
||'select ''''||DB||'';''||OS||'';''||log_mode||'';''||database_role||'';''||host_name||'';''||version||'';''||compatible||'';''||dbf_GB||'';''||seg_GB||'';''||tmp_GB|| '
||''';''||RMAN_Media||'';''||Type||'';''||status||'';''||Elapsed||'';''||DB_ARCs_Sz_GB||'';''||Backup_Sz_GB||'';''||compressed||'';''||BCT||'' '' '
||'from ( '
||'select a.name DB , platform_name OS , log_mode , database_role , host_name , b.version , value compatible , dbf_sz.dbf_GB dbf_GB, seg_sz.seg_GB seg_GB, tmp_sz.tmp_GB tmp_GB '
||', Media RMAN_Media,r.Type,r.status,Elapsed,to_char(DB_ARCs_Sz_GB) DB_ARCs_Sz_GB,Backup_Sz_GB,compressed,BCT '
||'from v$database a , v$instance b , v$parameter c , dbf_sz , seg_sz , tmp_sz , rman_rep r '
||'where c.name like ''compatible'' '
||'union '
||'select a.name DB , platform_name OS , log_mode , database_role , host_name , b.version , value compatible , dbf_sz.dbf_GB dbf_GB, seg_sz.seg_GB seg_GB, tmp_sz.tmp_GB tmp_GB '
||', ''No Backup Found'',null,null,null,null,null,null,null '
||'from v$database a , v$instance b , v$parameter c , dbf_sz , seg_sz , tmp_sz , dual '
||'where not exists ( select ''1'' from rman_rep ) and c.name like ''compatible'' ) ' ;

-- dbms_output.put_line (sCall);

EXECUTE IMMEDIATE sCall INTO v_res ;

dbms_output.put_line (v_res);

end ;

end case ;

end ;
/

exit


Results from 9i-10g-11g DBs :

$ for BDc in DB1 DB2 ; do sqlplus -s ina_svc/<psw>@${BDc} @rman_audit_backup.sql; done

DB1;AIX-Based Systems (64-bit);ARCHIVELOG;PRIMARY;sr-app-2;10.2.0.5.0;10.2.0.5;445;398;32;DISK;DB FULL;COMPLETED;01:16:10;416;52;YES;DISABLED
DB2;AIX-Based Systems (64-bit);ARCHIVELOG;PRIMARY;sr-app-2;10.2.0.5.0;10.2.0.5;30;20;2;DISK;DB FULL;COMPLETED;00:05:39;30;5;YES;DISABLED
. . .
DBn;Linux x86 64-bit;ARCHIVELOG;PRIMARY;db_srv-1.billettique.corp.fr;11.2.0.3.0;11.2.0.0.0;5;3;2;DISK;DB FULL;COMPLETED;00:01:08;3;1;YES;DISABLED

Or get a csv to be plugged into Excel, to sum volumes, durations and get the gains assuming that Incremental Backups are around 10 % volume of a FULL.


$ for BDc in DB1 DB2 … ; do sqlplus -s ina_svc/<psw>@${BDc} @rman_audit_backup.sql; done |tee rman_audit_backup.csv


BASE 9i
version
compatible
dbf_GB
seg_GB
tmp_GB
DB9i
9.2.0.6.0
9.2.0.0.0
3
3
4
TOT
FULL
3
3
4
INCR
0,3
Weekly GAIN
13,5


BASE 10g+
version
Type
Status
Elapsed
DB_ARCs
Sz_GB
Backup_Sz
GB
compressed
BCT
DB1
10.2.0.5.0
DB FULL
COMPLETED
01:16:39
416
52
YES
NO
DB2
10.2.0.5.0
DB FULL
COMPLETED
00:05:34
30
5
YES
NO
DBn
11.2.0.3.0
DB FULL
COMPLETED
00:00:52
2
1
YES
NO
DBo
11.2.0.3.0
DB FULL
COMPLETED
00:01:08
3
1
YES
NO
TOT
FULL
5:54:44
1330
186
INCR
0:35:28
133
18,6
Weekly GAIN
26:36:18
5985
837

4.2 Focus on a DB


select set_count,used_change_tracking bct,incremental_level INCR,sum(datafile_blocks) "Total_Blocks",
sum(blocks_read) "Blocks Reads",trunc(sum(blocks_read)/sum(datafile_blocks) * 10000)/100 as "% read",
sum(blocks) "Blocks Writes",trunc(sum(blocks)/sum(datafile_blocks) * 10000)/100 as "% write"
from   v$backup_datafile
group by set_count,used_change_tracking,incremental_level
order by 1 desc;


SET_COUNT
BCT
INCR
Total_Blocks
Blocks Reads
% read
Blocks Writes
% write
9464
NO

2424
2424
100
2424
100
9460
NO
2
12021438
12021438
100
74150
0,61
9459
NO
2
12021502
12021502
100
902794
7,5
9458
NO
2
12021502
12021502
100
39330
0,32
9457
NO
2
12021502
12021502
100
423534
3,52
9456
NO
2
12021670
12021670
100
132057
1,09
9449
NO

2424
2424
100
2424
100
9448
NO

2424
2424
100
2424
100
9444
NO
0
12019342
8722916
72,57
8489997
70,63
9443
NO
0
12019358
11870810
98,76
11553661
96,12
9442
NO
0
12019390
11907662
99,07
11602367
96,53
9441
NO
0
12019446
11879997
98,83
11604757
96,54
9440
NO
0
12019454
11888040
98,9
11730742
97,59
9432
NO

2424
2424
100
2424
100

As a result of the Write %, BCT should be installed.


5] RMAN Validate Backups

Backups are OK, but is it possible to Restore them ?
RMAN Dump files may have been erased and therefore, Restore is not possible : this should be checked before we need to an actual Restore !
One way is using the PREVIEW Option.
The other way uses a combination of : Oracle 12C
RMAN> run {
2> restore database validate ;
3> recover database validate header ;

My preferred method is compatible with 10G+ Instance : the first one, PREVIEW.
It will list every dumpfiles needed to restore ; we can then check if those dumps are available ( using ssh to remote host ).

5.1 RMAN Script with PREVIEW Option

$ cat rman_restor_db_preview_def_dsk.scr
#+-+-+-++-+-+-++-+-+-++-+-+-+-+-+-+-+
# RMAN preview script
# Database 10g+
# Media : DISK
# Catalog
# Default Last Backup
#+-+-+-++-+-+-++-+-+-++-+-+-+-+-+-+-+

connect catalog RCAT_CONNECT_STRING

run {

set until time "to_date('2018-10-12 11:50:00','YYYY-MM-DD HH24:MI:SS')";

RESTORE DATABASE PREVIEW ;

}

5.2 Shell / RMAN

$ cat rman_restor_db_preview_def_dsk_v2.ksh
#!/bin/ksh
# 26/02/16 - AUC
# Check Backups
# retour        0 ok 1 ko

# test args
if [ $# -lt 3 ] ; then
echo "Manque arguments"
echo "$0 PRO|NOPRO N_DAYS DEBUG_ON|OFF"
echo "N_DAYS Back, Current = 0"
echo "exemple d'appel:"
echo "$0 PRO 7 DEBUG_OFF"
echo "$0 NOPRO 1 DEBUG_OFF"
return 1 ; fi

envir=$1
N_DAYS=$2
Cmd=$3

MOTE=12
. /etc/profile${MOTE}.ora

rma_dir=/UTILS/rman_rep_daily/PREVIEW
rma_ori=rman_restor_db_preview_def_dsk.ori
rma_scr=rman_restor_db_preview_def_dsk.scr
file_gen=${rma_dir}/log/rman_restor_db_PREVIEW_dsk_${envir}_$(date '+%m%d%y_%H%M').log

find ${rma_dir}/log -name '*.log' -mtime +31 -exec rm {} \;

# Get PSW
function get_psw_adb {
XXX
print $PSW
}

# Get database list and version
function get_rcat_bds {
print $LIST
}

function get_bds_ver {
XXX
print $VER
}

function get_host {
bd=$1
co="usr/psw@${bd}"
ora_cmd="select UPPER(replace(HOST_NAME,'.cg13.fr','')) from v\$instance ;"
#ora_cmd="select UPPER(HOST_NAME) from v\$instance ;"
RET_V=$( sqlplus -s ${co} <<!
SET ECHO OFF NEWP 0 SPA 0 PAGES 0 FEED OFF HEAD OFF TRIMS ON TAB OFF
${ora_cmd}
!
)
print ${RET_V}
}

codret=0
ret_char=OK
scr_dir=/UTILS/scripts
str_ina_svc=usr/psw

# Plug de la Date - ARC
# %%DATE%%
# TZ="GMT+24" ; date '+%Y-%m-%d %H:%M:%S'
#new_date=$( /usr/linux/bin/date '+%Y-%m-%d %H:%M:%S' -d "${N_DAYS} days ago" )
N_D=$((${N_DAYS} * 24))
new_date=$( TZ="GMT+${N_D}" ; date '+%Y-%m-%d %H:%M:%S' )
sed "s/%%DATE%%/${new_date}/" ${rma_dir}/${rma_ori} > ${rma_dir}/${rma_scr}
print "Date Until: "|tee ${file_gen}
grep until ${rma_dir}/${rma_scr} | grep -v '#'|tee -a ${file_gen}

li_bdc=$( get_rcat_bds ${envir} )
for BDC in ${li_bdc} ; do

rma_log=${rma_dir}/log/rman_restor_db_preview_def_dsk_${envir}_${BDC}_$(date '+%m%d%y_%H%M').log

echo "\n*** $BDC - appel scr RMAN @${rma_dir}/${rma_scr} ***"|tee -a ${file_gen}
echo "\n*** $BDC - log ${rma_log} ***"|tee -a ${file_gen}

psw=$( get_psw_adb SYS ${BDC} )
ove=$( get_bds_ver ${BDC} )

if [[ ${ove} = '10' ]] ; then continue ; fi
. /etc/profile${ove}.ora

# using Dedicated
STR="SYS/${psw}@${BDC}D"
#echo "***** $STR *****"

export NLS_DATE_FORMAT='DD/MM/YYYY HH24:MI:SS'
rman target ${STR} @${rma_dir}/${rma_scr} log=${rma_log}

print "\n1/ result ERR|RMAN-|ORA- :"|tee -a ${file_gen}

#egrep "ERR|RMAN-|ORA-|not found" ${rma_log} > /dev/null
egrep -v "RMAN-06908|RMAN-06909" ${rma_log} |egrep "ERR|RMAN-|ORA-|no backup of log thread|be created automatically during restore" > /dev/null
if (( $? == 0 )) then print "\n!! Error execution rman : check log ${rma_log} !!\n"|tee -a ${file_gen} ;  codret=1 ; ret_char=KO ; continue ; else echo OK| tee -a ${file_gen} ; fi

print "\n2/ result Piece Name :"|tee -a ${file_gen}
#cat ${rma_log} |egrep -i 'Piece Name' |awk '{ print $3}' | xargs ls -l 2>&1 | egrep "does not exist|Permission denied|Aucun fichier|Permission non|No such file"

if [[ $Cmd = "DEBUG_ON" ]] ; then # Tst version
cat ${rma_log} |egrep -i 'Piece Name' |awk '{ print $3}' | xargs ssh ${BDC} "ls -l "
else # Prod version
cat ${rma_log} |egrep -i 'Piece Name' |awk '{ print $3}' | xargs ssh ${BDC} "ls -l " 2>&1 | egrep "does not exist|Permission denied|Aucun fichier|Permission non|No such file"
if (( $? == 0 )) then print "\n!! Error execution rman : check log ${rma_log} !!\n"|tee -a ${file_gen} ;  codret=1 ; ret_char=KO ; continue ; else echo OK| tee -a ${file_gen} ; fi
fi

print "\n3/ result Archive Logs:"|tee -a ${file_gen}
# ssh oracle@PROQU "ls -l /arch/pelun/PELUN1_24210_842120473.arc"

if [[ $Cmd = "DEBUG_ON" ]] ; then # Tst version
cat ${rma_log} |awk '{ print ($4=="A") ? $7 : ""}' | xargs ssh ${BDC} "ls -l "
else # Prod version
cat ${rma_log} |awk '{ print ($4=="A") ? $7 : ""}' | xargs ssh ${BDC} "ls -l " 2>&1 | egrep "does not exist|Permission denied|Aucun fichier|Permission non|No such file"
if (( $? == 0 )) then print "\n!! Error execution rman : check log ${rma_log} !!\n"|tee -a ${file_gen} ;  codret=1 ; ret_char=KO ; continue ;  else echo OK| tee -a ${file_gen} ; fi
fi

done

if [[ $Cmd = "DEBUG_OFF" ]] ; then
cat ${file_gen} | mailx -s "[RMAN] Check Restoration Preview - ${envir} - ${N_DAYS} days ago - status: ${ret_char}" 'dsit.dba@cg13.fr'
fi

return ${codret}

5.3 Run Shell

# RMAN Check
20 13 * * 1-5 /UTILS/rman_rep_daily/PREVIEW/rman_restor_db_preview_def_dsk_v2.ksh DEV 7 DEBUG_OFF
30 13 * * 1-5 /UTILS/rman_rep_daily/PREVIEW/rman_restor_db_preview_def_dsk_v2.ksh QUA 7 DEBUG_OFF
40 13 * * 1-5 /UTILS/rman_rep_daily/PREVIEW/rman_restor_db_preview_def_dsk_v2.ksh PPR 7 DEBUG_OFF

Mail sent :


[RMAN] Check Restoration Preview - PRO - 10 days ago - status: OK

Date Until:
set until time "to_date('2018-10-13 11:50:00','YYYY-MM-DD HH24:MI:SS')";

*** DBNAME - appel scr RMAN @/UTILS/oracle/dba/bao/rman_rep_daily/PREVIEW/rman_restor_db_preview_def_dsk.scr ***

*** DBNAME - log /UTILS/oracle/dba/bao/rman_rep_daily/PREVIEW/log/rman_restor_db_preview_def_dsk_PRO_DBNAME_102318_1350.log ***

1/ result ERR|RMAN-|ORA- :
OK

2/ result Piece Name :
OK

3/ result Archive Logs:
OK