Script (UNIX) to automate your Hot Backups


#! /bin/ksh
# The script can be tailored to meet your Environment
# Plug in appropriate values between the "<>" to meet your environment
# The following values needs to be replaced
# <ORACLE_SID>
# <ORACLE_HOME>
# <COLD_BACKUP_DIRECTORY>
# <email_address>
# <username>
# <password>

trap  2 3

# Set up environmental variables - Oracle specific
#
export ORACLE_SID=<ORACLE_SID>
export ORACLE_HOME=<ORACLE_HOME>
export PATH=$PATH:/$ORACLE_HOME/bin

# Set up variables to hold directory information
#
HOT=<HOT_BACKUP_DIRECTORY>
LOG=<BACKGROUND_DUMP_DEST>/alert_${ORACLE_SID}.log

# Make sure that the Lock File does not exists this confirms that
# the previous cron job has finished its activity of cold backup
#
if [ -f ${HOT}/hotbackup.lock ]; then
  mail <email_address> <<-EOF
    ERROR - HOT BACKUP For "${ORACLE_SID}" Has Failed
    Previous Hot Backup was not completely Successful !
  EOF
  exit 1
else
  touch ${HOT}/hotbackup.lock
fi

# Make sure that the Database Is up and running
# If not inform the concerned person
#
database_up=`ps -ef | grep pmon_${ORACLE_SID} | grep -v grep | wc -l`
if [ $database_up -eq 0 ]
then
  mail <email_address> <<-EOF
    ERROR - COLD BACKUP For "${ORACLE_SID}" Has Failed
    Database Should be up to take a trace of the data files - Please Investigate!
  EOF
  exit 1
fi

# Make sure that the Database Is running in archive log mode
# If not inform the concerned person
#
sqlplus /nolog <<-EOF
  connect / as sysdba
  spool ${HOT}/archive_mode.lst
  archive log list
  spool off
  EXIT
EOF
archive_mode=`grep -i "No Archive Mode*" ${HOT}/archive_mode.lst|grep -v grep|wc -l`
if [ $archive_mode -eq 1 ]
then
  mail <<email_address> <<-EOF
    ERROR - HOT BACKUP For "${ORACLE_SID}" Has Failed
  Database Is Not Running in Archive Log Mode as Desired
  during Hot Backup's - Please put the database in Archive Log Mode and restart!
  EOF
  exit 1
fi

# Find the count of 'alter tablespace .* begin backup' and
# 'alter tablespace .* end backup' in your alert logs
# if both are equal this signifies the previous hot backup is successful
#
if [ -f $LOG ] ; then
  Bgn_Bkp=egrep -ci '^alter tablespace .* begin backup' $LOG
  End_Bkp=egrep -ci '^alter tablespace .* end backup' $LOG
  Diff_Bkp=expr $Bgn_Bkp - $End_Bkp
else
  mail <email_address> <<-EOF
    ERROR - HOT BACKUP For "${ORACLE_SID}" Has Failed
    Could not locate Alert Log - Please Investigate !
  EOF
  exit 1
fi

# Logon to sqlplus - preferably as a DBA
# the sql script, generates a files called ora_HOT_backup.sql
# The file contains all the commands to perform hot backup's
# 1. Backup control file before starting hot backup.
# 2. Put first tablespace online.
# 3. Backup the datafile associated with the tablespaces and compress them (to save space).
# 4. Bring the first tablespace online.
# 5. Repeat steps 2 through 5 till all tablespaces are backed up
#
sqlplus <<username>/<password> <<-EOF
  column tablespace_name noprint
  column seqn noprint
  set pagesize 0
  set linesize 132
  set feedback off
  set sqlprompt ""
  Whenever SQLERROR exit FAILURE
  select chr(1) tablespace_name, -9999 seqn,
  'alter system switch logfile;'
  from dual
  UNION
  select chr(1) tablespace_name, -9998 seqn,
  'alter database backup controlfile to  ||
  '${HOT}/controlfile_${ORACLE_SID}.HOT.full.before reuse;'
  from dual
  UNION
  select tablespace_name, 0,
  'alter tablespace '||tablespace_name||' begin backup;'
  from sys.dba_tablespaces
  where status = 'ONLINE'
  UNION
  select tablespace_name, file_id,
  '!compress < '||file_name||'> ${HOT}/' ||
  substr(file_name,instr(file_name,'/',-1) + 1) || '.Z'
  from sys.dba_data_files
  where status = 'AVAILABLE'
  UNION
  select tablespace_name, 9999,
  'alter tablespace '||tablespace_name||' end backup;'
  from sys.dba_tablespaces
  where status = 'ONLINE'
  UNION
  select chr(255) tablespace_name, 9998 seqn,
  'alter database backup controlfile to  ||
  '${HOT}/controlfile_${ORACLE_SID}.HOT.full.after reuse;'
  from dual
  UNION
  select chr(255) tablespace_name, 9999 seqn,
  'alter system switch logfile;'
  from dual
  ORDER
  BY 1, 2
  spool ora_HOT_backup.sql
  /
  spool off
  start ora_HOT_backup.sql
  exit
EOF

# Find the count of 'alter tablespace .* begin backup' and
# 'alter tablespace .* end backup' in your alert logs
# if both are equal this signifies the previous hot backup is successful
# Else mail the concerned person associated with the backup's.
#
Bgn_Bkp=egrep -ci '^alter tablespace .* begin backup' $LOG
End_Bkp=egrep -ci '^alter tablespace .* end backup' $LOG
if [ $Bgn_Bkp != expr $End_Bkp + $Diff_Bkp ] ; then
  mail <email_address> <<-EOF
    ERROR : HOT BACKUP For "${ORACLE_SID}" Has Failed
    Number of "Begin Backup" statenents does not equal "End Backup"
    Please Investigate Immediately !
  EOF
  exit 1
fi

Script (UNIX) to automate your Cold Backups


#! /bin/ksh
 # The script can be tailored to meet your Environment
# Plug in appropriate values between the "<>" to meet your environment
# The following values needs to be replaced
# <ORACLE_SID>
# <ORACLE_HOME>
# <COLD_BACKUP_DIRECTORY>
# <email_address>
# <username>
# <password>
#
trap  2 3
#
# Set up environmental variables - Oracle specific
#
export ORACLE_SID=<ORACLE_SID>
export ORACLE_HOME=<ORACLE_HOME>
export PATH=$PATH:/$ORACLE_HOME/bin
#
# Set up variables to hold directory information
#
COLD=<COLD_BACKUP_DIRECTORY>
#
# Make sure that the Lock File does not exists this confirms that
# the previous cron job has finished its activity of cold backup
#
if [ -f ${COLD}/coldbackup.lock ]; then
  mail <email_address> <<EOF
ERROR - COLD BACKUP For "${ORACLE_SID}" Has Failed
Previous Cold Backup is not completed !
EOF
  exit 1
else
  touch ${COLD}/coldbackup.lock
fi
#
# Make sure that the Database Is up and running
# If not inform the concerned person
#
database_up=`ps -ef | grep pmon_${ORACLE_SID} | grep -v grep | wc -l`
if [ $database_up -eq 0 ]
then
  mail <email_address> <<EOF
ERROR - COLD BACKUP For "${ORACLE_SID}" Has Failed
Database Should be up to take a trace of the data files - Please Investigate!
EOF
  exit 1
fi

sqlplus <username>/<password> < column tablespace_name noprint
column seqn noprint
set pagesize 0
set linesize 132
set feedback off
set sqlprompt ""
Whenever SQLERROR exit FAILURE
SELECT 'compress < '||file_name||'> ${COLD}/' ||
substr(file_name,instr(file_name,'/',-1) + 1) || '.Z'
FROM sys.dba_data_files
UNION
SELECT 'compress < '||member||'> ${COLD}/' ||
substr(member,instr(member,'/',-1) + 1) || '.Z'
from sys.v$logfile
UNION
SELECT
'compress < '||name||'> ${COLD}/' ||
substr(name,instr(name,'/',-1) + 1) || '.Z'
FROM sys.v$controlfile
spool ora_COLD_backup.sh
/
spool off
exit
EOF
#
# Make sure that the Database Is Down Before you initiate the Cold Backup
# If not bring down the database
# If not successful inform the concerned Person
database_up=`ps -ef | grep pmon_${ORACLE_SID} | grep -v grep | wc -l`
if [ $ora_users_num -ne 0 ]
then
  sqlplus /nolog <<END
connect / as sysdba
shutdown
exit
END
fi
#
# Double Check if the Database is brugh down before you start cold backup
# If not inform the concerned person.
#
database_up=`ps -ef | grep pmon_${ORACLE_SID} | grep -v grep | wc -l`
if [ $database_up -ne 0 ]
then
  mail <email_address> <<EOF
ERROR - COLD BACKUP For "${ORACLE_SID}" Has Failed
Database could be brough down - Please Investigate !
EOF
  exit 1
fi
chmod +x ora_COLD_backup.sh
./ora_COLD_backup.sh
rm ${COLD}/coldbackup.lock

Script (UNIX) to automate your Logical Backup's or Exports


#! /bin/ksh
# The script can be tailored to meet your Environment
# Plug in appropriate values between the "<>" to meet your environment
# The following values needs to be replaced
# <ORACLE_SID>
# <ORACLE_HOME>
# <EXPORT_DIR>
# <email_address>
# <username>
# <password>
#
trap  2 3
#
# Set up environmental variables - Oracle specific
#
export EXPORT_DIR=<EXPORT_DIR>
export ORACLE_SID=<ORACLE_SID>
export ORACLE_HOME=<ORACLE_HOME>
export PATH=$PATH:/$ORACLE_HOME/bin
#
# Make sure that the Lock File does not exists this confirms that
# the previous cron job has finished its activity of cold backup
#
if [ -f ${EXPORT_DIR}/fullexport.lock ]; then
mail <email_address> <<EOF
ERROR - EXPORT BACKUP For "${ORACLE_SID}" Has Failed
Previous Export Backup is not completed !
EOF
exit 1
else
touch ${EXPORT_DIR}/fullexport.lock
fi
################################################################
#
# This function takes the Full export backup of the database.
# Export will be used only as a last resort if all other options
# of recovery fails. This involves creation of a new database and
# importing data into it.
#
# The parametr file fullexp.par is responsible for guiding how the export
# will behave. Please understand it thoroughly before starting
# the export procedure.
#
# It is Safe to Take Exports only when the database is up and
# no other users have logged on and nobody should be using
# the database. If export is taken while some users have logged
# on to the application and are using it, the export will be
# inconsistent and data integrity will be lost.
#
################################################################
#
# Check if the database is up or not.
#
database_up=`ps -ef|sed 's/ $//g' | grep "ora_...._${ORACLE_SID}" | grep -v grep | wc -l`
if [ $database_up -eq 0 ]
then
mail <email_address> <<EOF
ERROR - Export Backup for "${ORACLE_SID}" Has Failed
Database Is Not Up - Please Investigate !
EOF
exit 0
else
EXPORT_FILE_NAME=`date '+fullexport%y%m%d'`.dmp
LOG_FILE_NAME=`date '+fullexport%y%m%d'`.log
mknod ${EXPORT_DIR}/${EXPORT_FILE_NAME} p
chmod +rw ${EXPORT_DIR}/$EXPORT_FILE_NAME
#
# Building the export parameter file fullexp.par
#
cat <<END > ${EXPORT_DIR}/fullexp.par
FILE=${EXPORT_DIR}/${EXPORT_FILE_NAME}
FULL=Y
COMPRESS=Y
LOG=${EXPORT_DIR}/${LOG_FILE_NAME}
END
cat ${EXPORT_DIR}/${EXPORT_FILE_NAME} | compress > ${EXPORT_DIR}/${EXPORT_FILE_NAME}.Z &
exp <userid>/<password> parfile=${EXPORT_DIR}/fullexp.par
# compress ${EXPORT_DIR}/${EXPORT_FILE_NAME}
rm -f ${EXPORT_DIR}/fullexp.par
rm -f ${EXPORT_DIR}/fullexport.lock
mail <email_address> <<EOF
Export Backup for "${ORACLE_SID}" Completed
EOF
fi

PFILEs vs. SPFILEs


Initialization Parameter files: PFILEs vs. SPFILEs

When an Oracle Instance is started, the characteristics of the Instance are established by parameters specified within the initialization parameter file. These initialization parameters are either stored in a PFILE or SPFILE. SPFILEs are available in Oracle 9i and above. All prior releases of Oracle are using PFILEs.
SPFILEs provide the following advantages over PFILEs:
  • An SPFILE can be backed-up with RMAN (RMAN cannot backup PFILEs)
  • Reduce human errors. The SPFILE is maintained by the server. Parameters are checked before changes are accepted.
  • Eliminate configuration problems (no need to have a local PFILE if you want to start Oracle from a remote machine)
  • Easy to find - stored in a central location
What is the difference between a PFILE and SPFILE:
A PFILE is a static, client-side text file that must be updated with a standard text editor like "notepad" or "vi". This file normally reside on the server, however, you need a local copy if you want to start Oracle from a remote machine. DBA's commonly refer to this file as the INIT.ORA file.
An SPFILE (Server Parameter File), on the other hand, is a persistent server-side binary file that can only be modified with the "ALTER SYSTEM SET" command. This means you no longer need a local copy of the pfile to start the database from a remote machine. Editing an SPFILE will corrupt it, and you will not be able to start your database anymore.
How will I know if my database is using a PFILE or SPFILE:
Execute the following query to see if your database was started with a PFILE or SPFILE:

SQL> SELECT DECODE(value, NULL, 'PFILE', 'SPFILE') "Init File Type" 
       FROM sys.v_$parameter WHERE name = 'spfile';

You can also use the V$SPPARAMETER view to check if you are using a PFILE or not: if the "value" column is NULL for all parameters, you are using a PFILE.
Viewing Parameters Settings:
One can view parameter values using one of the following methods (regardless if they were set via PFILE or SPFILE):
  • The "SHOW PARAMETERS" command from SQL*Plus (i.e.: SHOW PARAMETERS timed_statistics)
  • V$PARAMETER view - display the currently in effect parameter values
  • V$PARAMETER2 view - display the currently in effect parameter values, but "List Values" are shown in multiple rows
  • V$SPPARAMETER view - display the current contents of the server parameter file.
Starting a database with a PFILE or SPFILE:
Oracle searches for a suitable initialization parameter file in the following order:
  • Try to use the spfile${ORACLE_SID}.ora file in $ORACLE_HOME/dbs (Unix) or ORACLE_HOME/database (Windows)
  • Try to use the spfile.ora file in $ORACLE_HOME/dbs (Unix) or ORACLE_HOME/database (Windows)
  • Try to use the init${ORACLE_SID}.ora file in $ORACLE_HOME/dbs (Unix) or ORACLE_HOME/database (Windows)
One can override the default location by specifying the PFILE parameter at database startup:
SQL> STARTUP PFILE='/oradata/spfileORCL.ora'
Note that there is not an equivalent "STARTUP SPFILE=" command. One can only use the above option with SPFILE's if the PFILE you point to (in the example above), contains a single 'SPFILE=' parameter pointing to the SPFILE that should be used. Example:
SPFILE=/path/to/spfile
Changing SPFILE parameter values:
While a PFILE can be edited with any text editor, the SPFILE is a binary file. The "ALTER SYSTEM SET" and "ALTER SYSTEM RESET" commands can be used to change parameter values in an SPFILE. Look at these examples:

SQL> ALTER SYSTEM SET open_cursors=300 SCOPE=SPFILE;

SQL> ALTER SYSTEM SET timed_statistics=TRUE
 COMMENT='Changed by Frank on 1 June 2003'
 SCOPE=BOTH
  SID='*';

The SCOPE parameter can be set to SPFILE, MEMORY or BOTH:

- MEMORY: Set for the current instance only. This is the default behaviour if a PFILE was used at STARTUP.

- SPFILE: update the SPFILE, the parameter will take effect with next database startup

- BOTH: affect the current instance and persist to the SPFILE. This is the default behaviour if an SPFILE was used at STARTUP.
The COMMENT parameter (optional) specifies a user remark.

The SID parameter (optional; only used with RAC) indicates the instance for which the parameter applies (Default is *: all Instances).
Use the following syntax to set parameters that take multiple (a list of) values:
SQL> ALTER SYSTEM SET utl_file_dir='/tmp/','/oradata','/home/' SCOPE=SPFILE;
Use this syntax to set unsupported initialization parameters (obviously only when Oracle Support instructs you to set it):
SQL> ALTER SYSTEM SET "_allow_read_only_corruption"=TRUE SCOPE=SPFILE;
Execute one of the following command to remove a parameter from the SPFILE:

SQL> ALTER SYSTEM RESET timed_statistics SCOPE=SPFILE SID=‘*’;
SQL> ALTER SYSTEM SET timed_statistics = '' SCOPE=SPFILE;

Converting between PFILES and SPFILES:
One can easily migrate from a PFILE to SPFILE or vice versa. Execute the following commands from a user with SYSDBA or SYSOPER privileges:

SQL> CREATE PFILE FROM SPFILE; 
SQL> CREATE SPFILE FROM PFILE;

One can also specify a non-default location for either (or both) the PFILE and SPFILE parameters. Look at this example:
SQL> CREATE SPFILE='/oradata/spfileORCL.ora' from PFILE='/oradata/initORCL.ora';
Here is an alternative procedure for changing SPFILE parameter values using the above method:
  • Export the SPFILE with: CREATE PFILE=‘pfilename’ FROM SPFILE = ‘spfilename’;
  • Edit the resulting PFILE with a text editor
  • Shutdown and startup the database with the PFILE option: STARTUP PFILE=filename
  • Recreate the SPFILE with: CREATE SPFILE=‘spfilename’ FROM PFILE=‘pfilename’;
  • On the next startup, use STARTUP without the PFILE parameter and the new SPFILE will be used.
Parameter File Backups:
RMAN (Oracle's Recovery Manager) will backup the SPFILE with the database control file if setting "CONFIGURE CONTROLFILE AUTOBACKUP" is ON (the default is OFF). PFILEs cannot be backed-up with RMAN. Look at this example:
RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON;
Use the following RMAN command to restore an SPFILE:
RMAN> RESTORE CONTROLFILE FROM AUTOBACKUP;

Finding tablespaces and their associated data-files

select substr(b.name,0,10) name, a.file#, a.ts#, status, from v$datafile a, v$tablespace b where a.ts#=b.ts#
Order by file#