Thursday, August 18, 2011

Managing multiple archive destinations with RMAN backup and restore process

Goal is to Explain how multiple archive destinations are handled during an RMAN backup and restore process

Specifying Archive Destinations

You can choose whether to archive redo logs to a single destination or multiplex them. If you want to archive only to a single destination, you specify that destination in the LOG_ARCHIVE_DEST initialization parameter. If you want to multiplex the archived logs, you can choose whether to archive to up to ten locations (using the LOG_ARCHIVE_DEST_n parameters) or to archive only to a primary and secondary destination (using LOG_ARCHIVE_DEST and LOG_ARCHIVE_DUPLEX_DEST).

Backing Up Archived Redo Log Files with BACKUP ARCHIVELOG

To back up archived redo logs, use the BACKUP ARCHIVELOG command at the RMAN prompt. This example uses a configured disk or sbt channel to back up one copy of each log sequence number for all archived redo logs:

BACKUP ARCHIVELOG ALL;

Even if your redo logs are being archived to multiple destinations and you use RMAN to back up archived redo logs, RMAN selects only one copy of the archived redo log file to include in the backup set. (Since logs with the same log sequence number are identical, there is no need to include more than one copy.)

RMAN Command: DELETE INPUT

DELETE INPUT will remove archivelogs from the first destination. It will also remove archivelogs from the second destination that was PREVIOUSLY backed up.

For example:

Backup #1

  • Backup archivelogs older than seven days from destination #1, and remove these files
  • Do not backup or remove any archivelogs in destination #2 has all files

Backup #2

  • For destination #1, backup archivelogs older than seven days and remove these files
  • For destination #2, backup archivelogs that satisfied backup criteria #1 (more than 14 days old) and remove them

Whereas a DELETE ALL INPUT will backup from one destination and delete both copies of the archivelog.

Backup and Delete from a Specified Archive Destination

If you'd like to only backup and remove from a single archive destination, use the LIKE clause:

eg:

RMAN> backup archivelog until time 'sysdate -7' like '/u04/oracle/admin/TEST/arch/%' delete
input;

The above will only backup and delete from the LIKE destination

If archive logs are backed up to multiple destinations, and if the required retention policy is required to be different for different destinations, then the following can be done:

RMAN> run {

backup archivelog all;
delete archivelog until time 'sysdate -1' like '/am3/oradata/arch/%';
delete archivelog until time 'sysdate -5' like '/am3/oradata/arch1/AM3P2/%';
}

The FRA and DELETE INPUT

RMAN will backup and remove the archivelogs in numerical order from _dest_1 to dest_10. However,
if one of the archive destinations is an FRA, RMAN will always backup and remove from the FRA
first, and then work on the numerical order of the log_archive_dest_x

eg.
If the following parameters were set:

  • log_archive_dest_1='location=/u002/oraarch/ORA1020
  • log_archive_dest_2='LOCATION=USE_DB_RECOVERY_FILE_DEST
  • log_archive_dest_3='location=/u002/oraarch3/ORA1020'

Oracle will backup and remove from the FRA, folllowed by archivelogs in log_archive_dest_1.
Finally, logs in log_archive_dest_3 will be removed.

Where do the restored archivelogs go?

During the restore process RMAN will check all archive destinations to make sure that the archivelog requested does not already exist. If the archivelog already exist in one of the destinations RMAN will not restore the file. If the archivelog does not exist in any of the destinations RMAN will restore it to the FRA if it exists. Otherwise it will restore it to the highest archive destination defined.


Restoring archivelog to FRA in ASM

When using the FRA and ASM, the archivelog will be restored to the current directory, rather than the time at which it was generated. Even if using the SET ARCHIVELOG DESTINATION, an alias will be created to the current directory.

For example, on the 16 Aug 2010, when restoring the 13 Aug archivelogs:

RMAN> run {
allocate channel c1 type 'sbt_tape';
set archivelog destination to '
+SHARED_FRA_DG01/P132/ARCHIVELOG/2010_08_13';
restore archivelog from time "to_date('13/08/2010:00:00:00','dd/mm/yyyy:hh24:mi:ss')"
until time "to_date('14/08/2010:00:00:00','dd/mm/yyyy:hh24:mi:ss')";
}

+SHARED_FRA_DG01/P132/ARCHIVELOG/2010_08_13
ASMCMD> ls -ltr
Type Redund Striped Time Sys Name
N 1_94528_708660567.dbf => +SHARED_FRA_DG01/P132/ARCHIVELOG/2010_08_16/thread_1_seq_94528.5341.727224533
N 1_94529_708660567.dbf => +SHARED_FRA_DG01/P132/ARCHIVELOG/2010_08_16/thread_1_seq_94529.3425.727224661
N 1_94530_708660567.dbf => +SHARED_FRA_DG01/P132/ARCHIVELOG/2010_08_16/thread_1_seq_94530.5644.727224779

PS: This content is an excerpt from oracle's metalink Article ID 443814.1 with few additional notes at the top.

Tuesday, May 31, 2011

Missing Sequence Numbers in a Table...

Title says it all I guess.
But still want to blog out though...
Its quite common that at least one column in one table in the database will be depending on Oracle SEQUENCE and there will be a code in place to get the NEXTVAL from that sequence to populate.
And I am pretty sure that because of few reasons the NEXTVAL that is fetched is not really committed to the table and thus there will be a sequence miss in the table.

The following query gets you all the sequences that were generated but never made it table.
----------------------------------------------------------------------------------------------
--with one sql. only catch is that the number of rows in the actual table should be
--less than or equal to the number of rows in dba_objects.
select missing_seqs
from (
select rownum missing_seqs from dba_objects
minus
select seq from santest --replace with the actual column an table name here
)
where missing_seqs <= (select max(seq) from santest); --replace with the actual column an table name here
----------------------------------------------------------------------------------------------
--pl/sql block for without any catches and gotchas...
set serveroutput on size unlimited
declare
t_missing_seq number;
t_start_seq number := 1; --replace this with the actual seq value that is started off in the table
t_max_seq number;
x char;
begin
select max(seq) into t_max_seq from santest; --replace santest with the actual table where the sequence column is. also replace (seq) witht the actual column name
for i in t_start_seq..t_max_seq loop
begin
select 'x'
into x
from santest --replace santest with the actual table
where seq = i; --replace seq with the actual column name
exception
when no_data_found then
dbms_output.put_line('Missing Sequence --> '||i);
end;
end loop;
end;
/
----------------------------------------------------------------------------------------------

Wednesday, May 25, 2011

Number of Rows per Partition in a Table

Simple and handy anonymous block to share that provides the total number of rows per partition in a given table:

___________________________________________________________________
set serveroutput on size unlimited
set echo off
set verify off
declare
cursor c1 is
select table_name,partition_name
from all_tab_partitions
where table_name = upper('&Table_Name');
t_count number:=0;
begin
for i in c1
loop
execute immediate 'select count(1) from '||i.table_name||' partition('||i.partition_name||')' into t_count;
dbms_output.put_line('The Partition '||i.partition_name||' of table '||i.table_name||' has '||t_count||' rows');
end loop;
end;
/
___________________________________________________________________