• No results found

Oracle DBA Automation Scripts

N/A
N/A
Protected

Academic year: 2021

Share "Oracle DBA Automation Scripts"

Copied!
58
0
0

Loading.... (view fulltext now)

Full text

(1)

Oracle DBA: Backup and Recovery

Scripts

By Rajendra Gutta

Having the right backup and recovery procedures is crucial to the operation of any database. It is the responsibility of the database administrator to protect the database from system faults, crashes, and natural calamities resulting from a variety of circumstances. Learn how to choose the best backup and recovery mechanism for your Oracle system.

Having the right backup and recovery procedures is the lifeblood of any database. Companies live on data, and, if that data is not available, the whole company collapses. As a result, it is the responsibility of the database administrator to protect the database from system faults, crashes, and natural calamities resulting from a variety of circumstances.

The choice of a backup and recovery mechanism depends mainly on the following factors:

• Database mode (ARCHIVELOG, NOARCHIVELOG)

• Size of the database

• Backup and recovery time

• uptime

• Type of data (OLTP, DSS, Data Warehouse). The types of backup are

• Offline backup (Cold or closed database backup)

• Online backup (Hot or open database backup)

• Logical export

Logical exports create an export file that contains a list of SQL statements to recreate the database. Export is performed when the database is open and does not affect users work. Offline backups can only be performed when the database is shut down cleanly, and the database will be unavailable to users while the offline backup is being performed. Online backups are performed when the database is open, and it does not affect users work. The database needs to run in ARCHIVELOG mode to perform online backups. The database can run in either ARCHIVELOG mode or NOARCHIVELOG mode. In ARCHIVELOG mode, the archiver (ARCH) process archives the redo log files to the archive destination directory. These archive files can be used to recover the database in the case of a failure. In NOARCHIVELOG mode, the redo log files are not archived.

When the database is running in ARCHIVELOG mode, the choice can be one or more of the following:

• Export

• Hot backup

• Cold backup

When the database is running in NOARCHIVELOG mode, the choice of backup is as follows:

• Export

• Cold backup

Cold Backup

Offline or cold backups are performed when the database is completely shutdown. The disadvantage of an offline backup is that it cannot be done if the database needs to be run 24/7. Additionally, you can only

(2)

recover the database up to the point when the last backup was made unless the database is running in ARCHIVELOG mode.

The general steps involved in performing a cold backup are shown in Figure 3.1. These general steps are used in writing cold backup scripts for Unix and Windows NT.

The steps in Figure 3.1 are explained as follows. Step 1—Generating File List

An offline backup consists of physically copying the following files:

• Data files

• Control files

• Init.ora and config.ora files

CAUTION

Backing up online redo log files is not advised in all cases, except when performing cold backup with the database running in NOARCHIVELOG mode. If you make a cold backup in ARCHIVELOG mode do not backup redo log files. There is a chance that you may accidentally overwrite your real online redo logs, preventing you from doing a complete recovery.

If your database is running in ARCHIVELOG mode, when you perform cold backup you should also backup archive logs that exist.

Before performing a cold backup, you need to know the location of the files that need to be backed up. Because the database structure changes day to day as more files get added or moved between directories, it is always better to query the database to get the physical structure of database before making a cold backup.

To get the structure of the database, query the following dynamic data dictionary tables:

• V$datafile Lists all the data files used in the database SQL>select name from v$datafile;

• Backup the control file and perform a trace of the control file using

(3)

SQL>alter database backup controlfile to trace;

• Init.ora and config.ora Located under $ORACLE_HOME/dbs directory Step 2—Shut down the database

You can shut down a database with the following commands: $su – oracle

$sqlplus "/ as sysdba" SQL>shutdown

Step 3—Perform a backup

In the first step, you generated a list of files to be backed up. To back up the files, you can use the Unix copy command (cp) to copy it to a backup location, as shown in the following code. You have to copy all files that you generated in Step 1.

$cp /u01/oracle/users01.dbf /u10/backup

You can perform the backup of the Init.ora and config.ora files as follows: $cp $ORACLE_HOME/dbs/init.ora /u10/backup

$cp $ORACLE_HOME/dbs/config.ora /u10/backup Step 4—Start the database

After the backup is complete, you can start the database as follows: $su – oracle

$sqlplus "/ as sysdba" SQL> startup

Hot Backup

An online backup or hot backup is also referred to as ARCHIVE LOG backup. An online backup can only be done when the database is running in ARCHIVELOG mode and the database is open. When the database is running in ARCHIVELOG mode, the archiver (ARCH) background process will make a copy of the online redo log file to archive backup location.

An online backup consists of backing up the following files. But, because the database is open while performing a backup, you have to follow the procedure shown in Figure 3.2 to backup the files:

• Data files of each tablespace

• Archived redo log files

• Control file

(4)

The general steps involved in performing hot backup are shown in Figure 3.2. These general steps are used in writing hot backup scripts for Unix and Windows NT.

The steps in Figure 3.2 are explained as follows.

Step 1—Put the tablespace in the Backup mode and copy the data files.

Assume that your database has two tablespaces, USERS and TOOLS. To back up the files for these two tablespaces, first put the tablespace in backup mode by using the ALTER statement as follows:

SQL>alter tablespace USERS begin backup;

After the tablespace is in Backup mode, you can use the SELECT statement to list the data files for the USERS tablespace, and the copy (cp) command to copy the files to the backup location. Assume that the USERS tablespace has two data files—users01.dbf and users02.dbf.

SQL>select file_name from dba_data_files where tablespace_name='USERS';

$cp /u01/oracle/users01.dbf /u10/backup $cp /u01/oracle/users01.dbf /u10/backup

The following command ends the backup process and puts the tablespace back in normal mode. SQL>alter tablespace USERS end backup;

You have to repeat this process for all tablespaces. You can get the list of tablespaces by using the following SQL statement:

SQL>select tablespace_name from dba_tablespaces; Step 2—Back up the control and Init.ora files.

To backup the control file,

SQL>alter database backup controlfile to '/u10/backup/control.ctl'; You can copy the Init.ora file to a backup location using

$cp $ORACLE_HOME/dbs/initorcl.ora /u10/backup Step 3—Stop archiving.

(5)

Archiving is a continuous process and, without stopping archiver, you might unintentionally copy the file that the archiver is currently writing. To avoid this, first stop the archiver and then copy the archive files to backup location. You can stop the archiver as follows:

SQL>alter system switch logfile; SQL>alter system archive log stop;

The first command switches redo log file and the second command stops the archiver process. Step 4—Back up the archive files.

To avoid backing up the archive file that is currently being written, we find the least sequence number that is to be archived from the V$LOG view, and then backup all the archive files before that sequence number. The archive file location is defined by the LOG_ARCHIVE_DEST_n parameter in the Init.ora file.

select min(sequence#) from v$log where archived='NO';

Step 5—Restart the archive process.

The following command restarts the archiver process: SQL>alter system archive log start; Now you have completed the hot backup of database.

An online backup of a database will keep the database open and functional for 24/7 operations. It is advised to schedule online backups when there is the least user activity on the database, because backing up the database is very I/O intensive and users can see slow response during the backup period. Additionally, if the user activity is very high, the archive destination might fill up very fast.

Database Crashes During Hot Backup

There can be many reasons for the database to crash during a hot backup—a power outage or rebooting of the server, for example. If these were to happen during a hot backup, chances are that tablespace would be left in backup mode. In that case you must manually recover the files involved, and the recovery operation would end the backup of tablespace. It's important to check the status of the files as soon as you restart the instance and end the backup for the tablespace if it's in backup mode.

select a.name,b.status from v$datafile a, v$backup b where a.file#=b.file# and b.status='ACTIVE';

or

select a.tablespace_name,a.file_name,b.status from dba_data_files a, v$backup b

where a.file_id=b.file# and b.status='ACTIVE';

This statement lists files with ACTIVE status. If the file is in ACTIVE state, the corresponding tablespace is in backup mode. The second statement gives the tablespace name also, but this can't be used unless the database is open. You need to end the backup mode of the tablespace with the following command: alter tablespace tablespace_name end backup;

Logical Export

Export is the single most versatile utility available to perform a backup of the database, de-fragment the database, and port the database or individual objects from one operating system to another operating system.

(6)

Export backup detects block corruption

Though you perform other types of backup regularly, it is good to perform full export of database at regular intervals, because export detects any data or block corruptions in the database. By using export file, it is also possible to recover individual objects, whereas other backup methods do not support individual object recovery.

Export can be used to export the database at different levels of functionality:

• Full export (full database export) (FULL=Y)

• User-level export (exports objects of specified users) (OWNER=userlist)

• Table-level export (exports specified tables and partitions) (TABLES=tablelist)

• Transportable tablespaces (TABLESPACES=tools, TRANSPORT_TABLESPACE=y) There are two methods of Export:

• Conventional Path (default)—Uses SQL layer to create the export file. The fact is that the SQL layer introduces CPU overhead due to character set, converting numbers, dates and so on. This is time consuming.

• Direct path (DIRECT=YES)—Skips the SQL layer and reads directly from database buffers or private buffers. Therefore it is much faster than conventional path.

We will discuss scripts to perform the full, user-level, and table-level export of database. The scripts also show you how to compress and split the export file while performing the export. This is especially useful if the underlying operating system has a limitation of 2GB maximum file limit.

Understand scripting

This chapter requires understanding of basic Unix shell and DOS batch programming techniques that are described in Chapter 2 "Building Blocks." That chapter explained some of the common routines that will be used across most of the scripts presented here.

This book could have provided much more simple scripts. But, considering standardization across all scripts and the reusability of individual sections for your own writing of scripts, I am focusing on providing a

comprehensive script, rather than a temporary fix. After you understand one script, it is easy to follow the flow for the rest of the scripts.

Backup and Recovery under Unix

The backup and recovery scripts discussed here have been tested under Sun Solaris 2.x, HP-UX 11.x and AIX 4.x. The use of a particular command is discussed if there is a difference between these operating systems. They might also work in higher versions of the same operating system. These scripts are written based on the common ground among these three Unix flavors. However, I advise that you test the scripts under your environment for both backup and recovery before using it as a regular backup script. This testing not only gives you confidence in the script, it also gives you an understanding of how to use the script in case a recovery is needed and gives you peace of mind when a crisis hits.

Backup Scripts for HP-UX, Sun Solaris, and AIX

The backup scripts provided here work for HP-UX, Sun Solaris, and AIX with one slight modification. That is, the scripts use v$parameter and v$controlfile to get the user dump destination and control file

information. Because in Unix the dollar sign ($) is a special character, you have to precede it with a forward slash (\) that tells Unix to treat it as a regular character. However, this is different in each flavor of Unix. AIX and HP-UX need one forward slash, and the Sun OS needs two forward slashes to make the dollar sign a regular character.

Sun OS 5.x needs two \\ AIX 4.x needs one \

(7)

HP-UX 11.x needs one \

These scripts are presented in modular approach. Each script consists of a number of small functions and a main section. Each function is designed to meet a specific objective so that they are easy to understand and modify. These small functions are reusable and can be used in the design of your own scripts. If you want to change a script to fit to your unique needs, you can do so easily in the function where you want the change without affecting the whole script.

After the backup is complete, it is necessary to check the backup status by reviewing log and error files generated by the scripts.

Cold Backup

Cold backup program (see Listing 3.1) performs the cold backup of the database under the Unix

environment. The script takes two input parameters—SID and OWNER. SID is the instance to be backed up, and OWNER is the Unix account under which Oracle is running. Figure 3.3 describes the functionality of the cold backup program. Each box represents a corresponding function in the program.

Listing 3.1

coldbackup_ux

##################################################################### # PROGRAM NAME:coldbackup_ux

# PURPOSE:Performs cold backup of the database. Database #should be online when you start

# the script. It will shutdown and take a cold backup and brings # the database up again

(8)

# USAGE:$coldbackup_ux SID OWNER

# INPUT PARAMETERS: SID(Instance name), OWNER(Owner of instance) ##################################################################### #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_verify(): Verify that database is online

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_verify(){

STATUS=´ps -fu ${ORA_OWNER} |grep -v grep| grep ora_pmon_${ORA_SID}´ funct_chk_ux_cmd_stat "Database is down for given SID($ORA_SID), Owner($ORA_OWNER). Can't generate files to be backed up"

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_verify_shutdown(): Verify that database is down

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_verify_shutdown(){

STATUS=´ps -fu ${ORA_OWNER} |grep -v grep| grep ora_pmon_${ORA_SID}´ if [ $? = 0 ]; then

echo "´date´" >> $LOGFILE

echo "COLDBACKUP_FAIL: ${ORA_SID}, Database is up, can't make

coldbackup if the database is online."|tee -a ${BACKUPLOGFILE} >> $LOGFILE exit 1

fi }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_shutdown_i(): Shutdown database in Immediate mode

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_shutdown_i(){ ${ORACLE_HOME}/bin/sqlplus -s << EOF / as sysdba shutdown immediate; exit EOF } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_shutdown_n(): Shutdown database in Normal mode

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_shutdown_n(){ ${ORACLE_HOME}/bin/sqlplus -s << EOF / as sysdba shutdown normal; exit EOF } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_startup_r(): Startup database in restricted mode

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_startup_r(){ ${ORACLE_HOME}/bin/sqlplus -s << EOF / as sysdba startup restrict; exit EOF } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_startup_n(): Startup database in normal mode

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_startup_n(){

(9)

${ORACLE_HOME}/bin/sqlplus -s << EOF / as sysdba startup; exit EOF } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_build_dynfiles(): Identify the files to backup

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_build_dynfiles(){

# Build datafile list

echo "Building datafile list ." >> ${BACKUPLOGFILE} datafile_list=´${ORACLE_HOME}/bin/sqlplus -s <<EOF / as sysdba

set heading off feedback off

select file_name from dba_data_files order by tablespace_name; exit

EOF´

echo "############### SQL for Temp Files " >> ${RESTOREFILE} ${ORACLE_HOME}/bin/sqlplus -s <<EOF >> ${RESTOREFILE} / as sysdba

set heading off feedback off

select 'alter tablespace '||tablespace_name||' add tempfile '||''|| file_name||''||' reuse'||';'

from dba_temp_files; exit

EOF

echo "Backingup controlfile and trace to trace file" >>${BACKUPLOGFILE} ${ORACLE_HOME}/bin/sqlplus -s <<EOF

/ as sysdba

set heading off feedback off

alter database backup controlfile to '${CONTROLFILE_DIR}/backup_control.ctl'; alter database backup controlfile to trace;

exit EOF

# Backup trace of control file

CONTROL=´ls -t ${udump_dest}/*.trc |head -1´ if [ ! -z "$CONTROL" ]; then

grep 'CONTROL' ${CONTROL} 1> /dev/null if test $? -eq 0; then

cp ${CONTROL} ${CONTROLFILE_DIR}/backup_control.sql fi

fi }

# Prepare restore file for control file

echo "###### Control File " >> ${RESTOREFILE}

echo "# Use your own discretion to copy control file, not advised unless required..." >> ${RESTOREFILE}

echo " End of backup of control file" >> ${BACKUPLOGFILE}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_cold_backup(): Perform cold backup

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_cold_backup(){

#Copy datafiles to backup location

echo "############### Data Files " >> ${RESTOREFILE} for datafile in ´echo $datafile_list´

do

echo "Copying datafile ${datafile} ..." >> ${BACKUPLOGFILE} #Prepare a restore file to restore coldbackup in case a restore is necessary

echo cp -p ${DATAFILE_DIR}/´echo $datafile|awk -F"/" '{print $NF}'´ $datafile >> ${RESTOREFILE}

(10)

cp -p ${datafile} ${DATAFILE_DIR}

funct_chk_ux_cmd_stat "Failed to copy datafile file to backup location"

done

#Copy current init<SID>.ora file to backup directory echo " Copying current init.ora file" >> ${BACKUPLOGFILE} cp -p ${init_file} ${INITFILE_DIR}/init${ORA_SID}.ora

funct_chk_ux_cmd_stat "Failed to copy init.ora file to backup location" echo "################ Init.ora File " >> ${RESTOREFILE}

echo cp -p ${INITFILE_DIR}/init${ORA_SID}.ora ${init_file} >> ${RESTOREFILE}

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_parm(): Check for input parameters

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_parm() {

if [ ${NARG} -ne 2 ]; then

echo "COLDBACKUP_FAIL: ${ORA_SID}, Not enough arguments passed" exit 1

fi }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_bkup_dir(): Create backup directories if not already existing #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_bkup_dir() { RESTOREFILE_DIR="${BACKUPDIR}/restorefile_dir" BACKUPLOG_DIR="${BACKUPDIR}/backuplog_dir" DATAFILE_DIR="${BACKUPDIR}/datafile_dir" CONTROLFILE_DIR="${BACKUPDIR}/controlfile_dir" REDOLOG_DIR="${BACKUPDIR}/redolog_dir" ARCLOG_DIR="${BACKUPDIR}/arclog_dir" INITFILE_DIR="${BACKUPDIR}/initfile_dir" BACKUPLOGFILE="${BACKUPLOG_DIR}/backup_log_${ORA_SID}" RESTOREFILE="${RESTOREFILE_DIR}/restorefile_${ORA_SID}" LOGFILE="${LOGDIR}/${ORA_SID}.log"

if [ ! -d ${RESTOREFILE_DIR} ]; then mkdir -p ${RESTOREFILE_DIR}; fi if [ ! -d ${BACKUPLOG_DIR} ]; then mkdir -p ${BACKUPLOG_DIR}; fi if [ ! -d ${DATAFILE_DIR} ]; then mkdir -p ${DATAFILE_DIR}; fi if [ ! -d ${CONTROLFILE_DIR} ]; then mkdir -p ${CONTROLFILE_DIR}; fi if [ ! -d ${REDOLOG_DIR} ]; then mkdir -p ${REDOLOG_DIR}; fi

if [ ! -d ${ARCLOG_DIR} ]; then mkdir -p ${ARCLOG_DIR}; fi if [ ! -d ${INITFILE_DIR} ]; then mkdir -p ${INITFILE_DIR}; fi if [ ! -d ${DYN_DIR} ]; then mkdir -p ${DYN_DIR}; fi

if [ ! -d ${LOGDIR} ]; then mkdir -p ${LOGDIR}; fi # Remove old backup

rm -f ${RESTOREFILE_DIR}/* rm -f ${BACKUPLOG_DIR}/* rm -f ${DATAFILE_DIR}/* rm -f ${CONTROLFILE_DIR}/* rm -f ${REDOLOG_DIR}/* rm -f ${ARCLOG_DIR}/* rm -f ${INITFILE_DIR}/*

echo "${JOBNAME}: coldbackup of ${ORA_SID} begun on ´date +\"%c\"´" > ${BACKUPLOGFILE}

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_get_vars(): Get environment variables

(11)

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_get_vars(){

ORA_HOME=´sed /#/d ${ORATABDIR}|grep -i ${ORA_SID}|nawk -F ":" '{print $2}'´

ORA_BASE=´echo ${ORA_HOME}|nawk -F "/" '{for (i=2; i<=NF-2; i++) print "/"$i}'´

ORACLE_BASE=´echo $ORA_BASE|tr -d " "´ init_file=$ORA_HOME/dbs/init$ORA_SID.ora

#log_arch_dest1=´sed /#/d $init_file|grep -i log_archive_dest| nawk -F "=" '{print $2}'´

#log_arch_dest=´echo $log_arch_dest1|tr -d "'"|tr -d '"'´ udump_dest=´${ORACLE_HOME}/bin/sqlplus -s <<EOF

/ as sysdba

set heading off feedback off select value from v\\$parameter where name='user_dump_dest'; exit

EOF´

if [ x$ORA_HOME = 'x' ]; then

echo "COLDBACKUP_FAIL: Can't get ORACLE_HOME from oratab file for $ORA_SID"|tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

exit 1 fi

if [ ! -f $init_file ]; then

echo "COLDBACKUP_FAIL: init$ORA_SID.ora does not exist in ORACLE_HOME/dbs"|tee -a ${BACKUPLOGFILE} >> ${LOGFILE} exit 1

fi

if [ x$udump_dest = 'x' ]; then

echo "COLDBACKUP_FAIL: user_dump_dest not defined in init$ORA_SID.ora"| tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

exit 1 fi

ORACLE_HOME=${ORA_HOME}; export ORACLE_HOME ORACLE_SID=${ORA_SID}; export ORACLE_SID }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_ux_cmd_stat(): Check the exit status of Unix command #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_ux_cmd_stat() {

if [ $? != 0 ]; then

echo "´date´" |tee -a ${BACKUPLOGFILE} >> ${LOGFILE} echo "COLDBACKUP_FAIL: ${1} "| tee -a ${BACKUPLOGFILE} >> ${LOGFILE} exit 1 fi } ############################################################ # MAIN ############################################################ NARG=$# ORA_SID=$1 ORA_OWNER=$2

# Set environment variables BACKUPDIR="/u02/${ORA_SID}/cold" ORATABDIR=/etc/oratab

TOOLS="/u01/oracomn/admin/my_dba" DYN_DIR="${TOOLS}/DYN_FILES"

(12)

LOGDIR="${TOOLS}/localog" JOBNAME="dbcoldbackup"

echo " Starting coldbackup of ${ORA_SID} " funct_chk_parm funct_chk_bkup_dir funct_get_vars funct_verify funct_build_dynfiles funct_shutdown_i funct_startup_r funct_shutdown_n funct_verify_shutdown funct_cold_backup funct_startup_n

echo "${ORA_SID}, Coldbackup Completed successfully on ´date +\"%c\"´" |tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

######## END MAIN ##########################

Cold Backup Script under Unix Checklist

• In the main function, set correct values for the BACKUPDIR, ORATABDIR, and TOOLS variables highlighted in the cold backup script. The default location of ORATABDIR is different for each flavor of Unix. For information about the default location of the ORATAB file for different flavors of Unix, refer to Chapter 13, "Unix, Windows NT, and Oracle."

• Check for the existence of SID in oratab file. If not already there, you must add the instance.

• Check for existence of initSID.ora file in the ORACLE_HOME/dbs directory. If it is in a different location, you can create a soft link to the ORACLE_HOME/dbs directory.

• Pass SID and OWNER as parameters to the program.

• The database must be running when you start the program. It gets required information by querying the database and then shuts down the database and performs cold backup.

• main() The main function defines the variables required and calls the functions to be executed. The variables BACKUPDIR defines the backup location, ORATABDIR defines the oratab file

location. oratab files maintain the list of instances and their home directories on the machine. This file is created by default when oracle is installed. If it is not there, you must create one. OWNER is the owner of Oracle software directories. A sample oratab file can be found at the end of the chapter.

• funct_get_vars() This function gets ORACLE_HOME from the oratab file and

USER_DUMP_DEST from the initSID.ora file. The value of USER_DUMP_DEST is used to back up the trace of the control file.

• funct_build_dynfiles() This function generates a list of files from the database for backup. It also creates SQL statements for temporary files. These temporary files do not need to be backed up, but can be recreated when a restore is performed. These temporary files are session-specific and do not have any content when the database is closed.

• funct_shutdown_i() This function shuts down the database in Immediate mode, so that any user connected to the database will be disconnected immediately.

• funct_startup_r() This function starts up the database in Restricted mode, so that no one can connect to the database except users with Restrict privileges.

• funct_shutdown_n() This function performs a clean shutdown of the database.

• funct_chk_ux_cmd_stat() This function is used to check the status of Unix commands, especially after copying files to a backup location.

Restore File

A cold backup program creates a restore file that contains the commands to restore the database. This functionality is added based on the fact that a lot of DBAs perform backups but, when it comes to recovery, they will not have any procedures to make the recovery faster. With the restore file, it is easier to restore files to the original location because it has all the commands ready to restore the backup. Otherwise, you need to know the structure of the database—what files are located where. A sample restore file is shown in Listing 3.2.

(13)

Listing 3.2 Sample Restore File

######### SQL for Temp Files

alter tablespace TEMP add tempfile '/u03/oracle/DEV/data/temp03.dbf' reuse; alter tablespace TEMP add tempfile '/u03/oracle/DEV/data/temp04.dbf' reuse; ######### Data Files cp -p /bkp/DEV/cold/datafile_dir/INDX01.dbf /u02/oracle/DEV/data/INDX01.dbf cp -p /bkp/DEV/cold/datafile_dir/RBS01.dbf /u02/oracle/DEV/data/RBS01.dbf cp -p /bkp/DEV/cold/datafile_dir/SYSTEM01.dbf /u02/oracle/DEV/data/SYSTEM01.dbf cp -p /bkp/DEV/cold/datafile_dir/TEMP01.dbf /u02/oracle/DEV/data/TEMP01.dbf cp -p /bkp/DEV/cold/datafile_dir/USERS01.dbf /u02/oracle/DEV/data/USERS01.dbf ######### Control Files cp -p /bkp/DEV/cold/controlfile_dir/cntrl01.dbf /u02/oracle/DEV/data/cntrl01.dbf ######### Init.ora File cp -p /bkp/DEV/cold/initfile_dir/initDEV.ora /u02/apps/DEV/oracle/8.1.7/ dbs/initDEV.ora

Cold Backup Troubleshooting and Status Check

The important thing here is that the backup log file defined by BACKUPLOGFILE contains detailed

information about each step of the backup process. This is a very good place to start investigating why the backup failed or for related errors. This file will also have the start and end time of the backup.

A single line about the success or failure of a backup is appended to SID.log file every time a backup is performed. This file is located under the directory defined by the LOGDIR variable. This file also has the backup completion time. A separate file is created for each instance. This single file maintains the history of performed backups and their status and timing information. The messages for a cold backup are

'COLDBACKUP_FAIL' if a cold backup failed and 'Coldbackup Completed successfully' if a backup completes successfully.

Apart from the BACKUPLOGFILE and SID.log files, it is always good to capture the out-of-the-ordinary errors displayed onscreen if you are running the backup unattended. You can capture these errors by running the command shown next. The same thing can be done for hot backups. This command captures onscreen errors to the coldbackup.log file.

coldbackup_ux SID OWNER 1> coldbackup.log 2>&1

The following is an excerpt from the SID.log file:

Tue Jul 18 16:48:46 EDT 2000

COLDBACKUP_FAIL: DEV, Failed to copy control file to backup location

BACKUPLOGFILE

Listing 3.3 Sample

BACKUPLOGFILE

—dbcoldbackup: coldbackup of DEV begun on Sun May 20 21:15:27 2001 dbcoldbackup: building datafile list .

dbcoldbackup: Building controlfile list

Copying datafile /u02/oracle/DEV/data/INDX01.dbf ... Copying datafile /u02/oracle/DEV/data/RBS01.dbf ... Copying datafile /u02/oracle/DEV/data/SYSTEM01.dbf ... Copying datafile /u02/oracle/DEV/data/TEMP01.dbf ... Copying datafile /u02/oracle/DEV/data/USERS01.dbf ... Copying control file /u02/oracle/DEV/data/cntrl01.dbf ... Copying redolog file /u03/oracle/DEV/data/log01a.dbf ... Copying redolog file /u03/oracle/DEV/data/log01b.dbf ... Copying current init.ora file

(14)

Hot Backup

Listing 3.4 provides the script to perform the hot backup of a database under the Unix

environment. The hot backup script takes two input parameters—SID and OWNER. SID is the

instance to be backed up, and OWNER is the Unix account under which Oracle is running.

Figure 3.4

shows the functionality of the hot backup program. Each box represents a

corresponding function in the program.

Listing 3.4

hotbackup_ux

##################################################################### # PROGRAM NAME: hotbackup_ux

# PURPOSE: This utility will perform a warm backup of # the database

# USAGE: $hotbackup_ux SID OWNER

# INPUT PARAMETERS: SID(Instance name), OWNER(Owner of instance) ##################################################################### #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_verify(): Verify that database is online

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_verify(){

STATUS=´ps -fu ${ORA_OWNER} |grep -v grep| grep ora_pmon_${ORA_SID}´ funct_chk_ux_cmd_stat "Database is down for given SID($ORA_SID),

(15)

Owner($ORA_OWNER). Can't perform hotbackup " }

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_dblogmode(): Check DB log mode

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_dblogmode(){

STATUS=´${ORACLE_HOME}/bin/sqlplus -s <<EOF / as sysdba

set heading off feedback off select log_mode from v\\$database; exit

EOF´

if [ $STATUS = "NOARCHIVELOG" ]; then

echo "´date´" |tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

echo "HOTBACKUP_FAIL: $ORA_SID is in NOARCHIVELOG mode. Can't perform hotbackup " |tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

exit 1 fi

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_control_backup(): Backup control file

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_control_backup(){

echo "Begin backup of controlfile and trace to trace file" >>${BACKUPLOGFILE} ${ORACLE_HOME}/bin/sqlplus -s <<EOF

/ as sysdba

set heading off feedback off

alter database backup controlfile to '${CONTROLFILE_DIR}/backup_control.ctl'; alter database backup controlfile to trace;

exit EOF

# Backup trace of control file

CONTROL=´ls -t ${udump_dest}/*.trc |head -1´ if [ ! -z "$CONTROL" ]; then

grep 'CONTROL' ${CONTROL} 1> /dev/null if test $? -eq 0; then

cp ${CONTROL} ${CONTROLFILE_DIR}/backup_control.sql fi

fi

# Prepare restore file for control file

echo "###### Control File " >> ${RESTOREFILE}

echo "# Use your own discretion to copy control file, not advised unless required..." >> ${RESTOREFILE}

echo " End of backup of control file" >> ${BACKUPLOGFILE} }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_archivelog_backup(): Backup archivelog files

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_archivelog_backup(){

echo "Begin backup of archived redo logs" >> ${BACKUPLOGFILE}

#Switch logs to flush current redo log to archived redo before back up ${ORACLE_HOME}/bin/sqlplus -s <<EOF

/ as sysdba

set heading off feedback off alter system switch logfile; alter system archive log stop;

(16)

exit EOF

# This gets the redo sequence number that is being archived # and remove this from the list of files to be backed up ARCSEQ=´${ORACLE_HOME}/bin/sqlplus -s <<EOF

/ as sysdba

set heading off feedback off select min(sequence#) from v\\$log where archived='NO';

exit EOF´

#Get current list of archived redo log files

ARCLOG_FILES=´ls ${log_arch_dest}/*|grep -v $ARCSEQ´ ${ORACLE_HOME}/bin/sqlplus -s <<EOF

/ as sysdba

set heading off feedback off alter system archive log start; exit

EOF

#Prepare restore file for arc log files

echo "##### Archive Log Files" >> ${RESTOREFILE} for arc_file in ´echo $ARCLOG_FILES´

do

echo cp -p ${ARCLOG_DIR}/´echo $arc_file|awk -F"/" '{print $NF}'´ $arc_file >> ${RESTOREFILE}

done

#Copy arc log files to backup location

#remove the archived redo logs from the log_archive_dest if copy is successful cp -p ${ARCLOG_FILES} ${ARCLOG_DIR}

if [ $? = 0 ]; then rm ${ARCLOG_FILES} else

echo "´date´" |tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

echo "HOTBACKUP_FAIL: Failed to copy Archive log files" | tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

exit 1 fi

echo "End backup of archived redo logs" >> ${BACKUPLOGFILE} }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_init_backup(): Backup init.ora file

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_init_backup(){

#Copy current init<SID>.ora file to backup directory

echo " Copying current init${ORA_SID}.ora file" >> ${BACKUPLOGFILE} cp -p ${init_file} ${INITFILE_DIR}/init${ORA_SID}.ora

funct_chk_ux_cmd_stat "Failed to copy init.ora file to backup location" # Prepare restore file for init.ora

echo "############# Parameter Files" >> ${RESTOREFILE}

echo cp -p ${INITFILE_DIR}/init${ORA_SID}.ora ${init_file} >> ${RESTOREFILE} }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_temp_backup(): Prepre SQL for temp files

(17)

funct_temp_backup(){

echo "############# Recreate the following Temporary Files" >> ${RESTOREFILE} ${ORACLE_HOME}/bin/sqlplus -s <<EOF >> ${RESTOREFILE}

/ as sysdba

set heading off feedback off

select 'alter tablespace '||tablespace_name||' add tempfile '||''|| file_name||''||' reuse'||';' from dba_temp_files; exit EOF } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: #funct_hot_backup(): Backup datafiles

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_hot_backup(){

# Get the list of tablespaces

echo "Building tablespace list " >> ${BACKUPLOGFILE} tablespace_list=´${ORACLE_HOME}/bin/sqlplus -s <<EOF / as sysdba

set heading off feedback off

select distinct tablespace_name from dba_data_files order by tablespace_name;

exit EOF´

echo "##### DATE:" ´date´ > ${RESTOREFILE}

echo "####Data Files(Please restore only corrupted files)" >> ${RESTOREFILE} for tblspace in ´echo $tablespace_list´

do

# Get the datafiles for the current tablespace datafile_list=´${ORACLE_HOME}/bin/sqlplus -s <<EOF / as sysdba

set heading off feedback off

select file_name from dba_data_files where tablespace_name = '${tblspace}'; exit

EOF´

echo " Beginning back up of tablespace ${tblspace}..." >> ${BACKUPLOGFILE} ${ORACLE_HOME}/bin/sqlplus -s <<EOF

/ as sysdba

set heading off feedback off

alter tablespace ${tblspace} begin backup; exit

EOF

# Copy datafiles of current tablespace for datafile in ´echo $datafile_list´ do

echo "Copying datafile ${datafile}..." >> ${BACKUPLOGFILE} # The next command prepares restore file

echo cp -p ${DATAFILE_DIR}/´echo $datafile|awk -F"/" '{print $NF}'´ $datafile >> ${RESTOREFILE}

cp -p ${datafile} ${DATAFILE_DIR} if [ $? != 0 ]; then

echo "´date´" |tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

echo "HOTBACKUP_FAIL: Failed to copy file to backup location "| tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

# Ending the tablespace backup before exiting ´${ORACLE_HOME}/bin/sqlplus -s <<EOF

(18)

set heading off feedback off

alter tablespace ${tblspace} end backup; exit EOF´ exit 1 fi done ${ORACLE_HOME}/bin/sqlplus -s <<EOF / as sysdba

set heading off feedback off

alter tablespace ${tblspace} end backup; exit

EOF

echo " Ending back up of tablespace ${tblspace}.." >> ${BACKUPLOGFILE} done

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_parm(): Check for input parameters

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_parm() {

if [ ${NARG} -ne 2 ]; then

echo "HOTBACKUP_FAIL: ${ORA_SID}, Not enough arguments passed" exit 1

fi }

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

# funct_chk_bkup_dir(): Create backup directories if not already existing #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_bkup_dir() { RESTOREFILE_DIR="${BACKUPDIR}/restorefile_dir" BACKUPLOG_DIR="${BACKUPDIR}/backuplog_dir" DATAFILE_DIR="${BACKUPDIR}/datafile_dir" CONTROLFILE_DIR="${BACKUPDIR}/controlfile_dir" REDOLOG_DIR="${BACKUPDIR}/redolog_dir" ARCLOG_DIR="${BACKUPDIR}/arclog_dir" INITFILE_DIR="${BACKUPDIR}/initfile_dir" BACKUPLOGFILE="${BACKUPLOG_DIR}/backup_log_${ORA_SID}" RESTOREFILE="${RESTOREFILE_DIR}/restorefile_${ORA_SID}" LOGFILE="${LOGDIR}/${ORA_SID}.log"

if [ ! -d ${RESTOREFILE_DIR} ]; then mkdir -p ${RESTOREFILE_DIR}; fi if [ ! -d ${BACKUPLOG_DIR} ]; then mkdir -p ${BACKUPLOG_DIR}; fi if [ ! -d ${DATAFILE_DIR} ]; then mkdir -p ${DATAFILE_DIR}; fi

if [ ! -d ${CONTROLFILE_DIR} ]; then mkdir -p ${CONTROLFILE_DIR}; fi if [ ! -d ${REDOLOG_DIR} ]; then mkdir -p ${REDOLOG_DIR}; fi

if [ ! -d ${ARCLOG_DIR} ]; then mkdir -p ${ARCLOG_DIR}; fi if [ ! -d ${INITFILE_DIR} ]; then mkdir -p ${INITFILE_DIR}; fi if [ ! -d ${DYN_DIR} ]; then mkdir -p ${DYN_DIR}; fi

if [ ! -d ${LOGDIR} ]; then mkdir -p ${LOGDIR}; fi # Remove old backup

rm -f ${RESTOREFILE_DIR}/* rm -f ${BACKUPLOG_DIR}/* rm -f ${DATAFILE_DIR}/* rm -f ${CONTROLFILE_DIR}/*

(19)

rm -f ${REDOLOG_DIR}/* rm -f ${ARCLOG_DIR}/* rm -f ${INITFILE_DIR}/*

echo "${JOBNAME}: hotbackup of ${ORA_SID} begun on ´date +\"%c\"´" > ${BACKUPLOGFILE}

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_get_vars(): Get environment variables

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_get_vars(){

ORA_HOME=´sed /#/d ${ORATABDIR}|grep -i ${ORA_SID}|nawk -F ":" '{print $2}'´ ORA_BASE=´echo ${ORA_HOME}|nawk -F "/" '{for (i=2; i<=NF-2; i++)

print "/"$i}'´

ORACLE_BASE=´echo $ORA_BASE|tr -d " "´ init_file=$ORA_HOME/dbs/init$ORA_SID.ora

#log_arch_dest1=´sed /#/d $init_file|grep -i log_archive_dest| nawk -F "=" '{print $2}'´

#log_arch_dest=´echo $log_arch_dest1|tr -d "'"|tr -d '"'´ udump_dest=´${ORACLE_HOME}/bin/sqlplus -s <<EOF

/ as sysdba

set heading off feedback off select value from v\\$parameter where name='user_dump_dest'; exit

EOF´

if [ x$ORA_HOME = 'x' ]; then

echo "HOTBACKUP_FAIL: can't get ORACLE_HOME from oratab file for $ORA_SID" | tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

exit 1 fi

if [ ! -f $init_file ]; then

echo "HOTBACKUP_FAIL: init$ORA_SID.ora does not exist in ORACLE_HOME/dbs" | tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

exit 1 fi

if [ x$log_arch_dest = 'x' -o x$udump_dest = 'x' ]; then

echo "HOTBACKUP_FAIL: user_dump_dest or log_archive_dest not defined " | tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

exit 1 fi

ORACLE_HOME=${ORA_HOME}; export ORACLE_HOME ORACLE_SID=${ORA_SID}; export ORACLE_SID }

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_ux_cmd_stat(): Check the exit status of Unix command #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_ux_cmd_stat() {

if [ $? != 0 ]; then

echo "´date´" |tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

echo "HOTBACKUP_FAIL:${1} "|tee -a ${BACKUPLOGFILE} >> ${LOGFILE} exit 1

fi }

(20)

############################################################ # MAIN ############################################################ NARG=$# ORA_SID=$1 ORA_OWNER=$2

# Set environment variables

BACKUPDIR="/u02/${ORA_SID}/hot" ORATABDIR=/etc/oratab TOOLS="/u01/oracomn/admin/my_dba" log_arch_dest="/export/home/orcl/arch" DYN_DIR="${TOOLS}/DYN_FILES" LOGDIR="${TOOLS}/localog" JOBNAME="dbhotbackup"

echo " Starting hotbackup of .... ${ORA_SID}" funct_chk_parm funct_chk_bkup_dir funct_get_vars funct_verify funct_chk_dblogmode funct_hot_backup funct_temp_backup funct_control_backup funct_archivelog_backup funct_init_backup

echo "${ORA_SID}, hotbackup Completed successfully on ´date +\"%c\"´" | tee -a ${BACKUPLOGFILE} >> ${LOGFILE}

######## END MAIN #########################

Hot Backup Script under Unix Checklist

In the main function, set the correct values for BACKUPDIR, ORATABDIR, TOOLS, and

log_arch_dest variables highlighted in the script. The default location of ORATABDIR is

different for each flavor of Unix.

Check for existence of the SID instance in the oratab file. If not already there, you must

add the instance.

Check for the existence of the initSID.ora file in the ORACLE_HOME/dbs directory. If it is

in a different location, you must create a soft link to the ORACLE_HOME/dbs directory.

Pass SID and OWNER as parameters to the program:

• main() BACKUPDIR defines the backup location. ORATABDIR defines the oratab file

location. oratab files maintain the list of instances and their home directories on the

machine. This file is created by default when Oracle is installed. If it is not there, you must

create one. OWNER is the owner of the Oracle software directories.

• funct_get_vars() Make sure that the USER_DUMP_DEST parameter is set correctly in Init.ora file. I was reluctant to get LOG_ARCHIVE_DEST from the Init.ora file because

there are some changes between Oracle 7 and 8 in the way the archive destination is

defined. There are a variety of ways that you can define log_archive_dest based on how

many destinations you are using. Consequently, I have given the option to define

log_archive_dest in main function.

• funct_temp_backup() Oracle 7 and Oracle 8 support permanent temporary tablespaces

(created with create tablespce tablespace_name ... temporary). Apart from this,

(21)

Oracle 8I has new features to create temporary tablespaces that do not need back up

(created with create tablespace temporary...). Data in these temporary tablespaces is

session-specific and gets deleted as soon as the session is disconnected. Because of the

nature of these temporary tablespaces, you do not need to back them up; in the case of a

restore, you can just add the data file for these temporary tablespaces. The files for these

temporary tablespaces are listed under the dba_temp_files data dictionary view.

• funct_control_backup() In addition to taking backup of control file, this function also

backs up the trace of the control file. The trace of the control file will be useful to examine

the structure of the database. This is the single most important piece of information that

you need to perform a good recovery, especially if the database has hundreds of files.

• funct_chk_bkup_dir() This function creates backup directories for data, control, redo

log, archivelog, init files, restore files, and backup log files.

Restore file

The restore file for hot backup looks similar to cold backup. Please refer to the explanation under

the heading restore file for cold backup.

Hot Backup Troubleshooting and Status Check

The important thing here is that the backup log file defined by (BACKUPLOGFILE) contains

detailed information about each step of the backup process. This is a very good place to start

investigating why a backup has failed or for related errors. This file will also have the start and end

time of the backup.

A single line about the success or failure of a backup is appended to the SID.log file every time a

backup is performed. This file is located under the directory defined by the LOGDIR variable. This

file also has the backup completion time. A separate file is created for each instance. This single

file maintains the history of the performed backups, their status, and timing information. The

messages for a hot backup are 'HOTBACKUP_FAIL', if the hot backup failed, and 'Hotbackup

Completed successfully', if the backup completes successfully.

The following is an excerpt from the log file:

Tue Jul 18 16:48:46 EDT 2000

HOTBACKUP_FAIL: DEV, Not enough arguments passed

Export

The export program (see Listing 3.5) performs a full export of the database under Unix

environment. The export script takes two input parameters—SID and OWNER. SID is the instance to

be backed up, and OWNER is the Unix account under which Oracle is running.

Figure 3.5

shows the

functionality of the export and split export programs. Each box represents a corresponding

function in the program.

Figure 3.5

Functions in export and split export scripts for Unix.

Listing 3.5

xport_ux

###################################################################### # PROGRAM NAME: xport_ux

# PURPOSE: Performs export of the database # USAGE: $xport_ux SID OWNER

# INPUT PARAMETERS: SID(Instance name), OWNER(Owner of instance) )

(22)

###################################################################### #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_verify(): Verify that database is online

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_verify(){

STATUS=´ps -fu ${ORA_OWNER} |grep -v grep| grep ora_pmon_${ORA_SID}´ funct_chk_unix_command_status "Database is down for given SID($ORA_SID), Owner($ORA_OWNER). Can't perform export "

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_cleanup(): Cleanup interim files

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_cleanup() {

echo "Left for user convenience" > /dev/null }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_build_parfile(): This will create parameter file

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_build_parfile() {

# This line makes sure that it always creates a new parameter file echo " " >${PARFILE}

echo "userid=system/manager">>${PARFILE} # if you use connect string. see next line. #userid=system/manager@${CON_STRING} #echo "Owner=scott">>${PARFILE} #echo "Tables=scott.T1">>${PARFILE} echo "Full=Y">>${PARFILE} #echo "Direct=Y">>${PARFILE} echo "Grants=Y">>${PARFILE} echo "Indexes=Y">>${PARFILE} echo "Rows=Y">>${PARFILE} echo "Constraints=Y">>${PARFILE} echo "Compress=N">>${PARFILE} echo "Consistent=Y">>${PARFILE} echo "File=${FILE}">>${PARFILE} echo "Log=${EXPORT_DIR}/${ORA_SID}.exp.log">>${PARFILE} } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_export(): Export the database

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_export() {

# Remove old export file rm -f ${FILE}

${ORACLE_HOME}/bin/exp parfile=${PARFILE} if [ $? != 0 ]; then

echo ´date´ >> $LOGDIR/${ORA_SID}.log

echo "EXPORT_FAIL: ${ORA_SID}, Export Failed" >> $LOGDIR/${ORA_SID}.log funct_cleanup

exit 1 fi

(23)

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_parm(): Check for input parameters

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_parm() {

if [ ${NARG} -ne 2 ]; then

echo "EXPORT_FAIL: ${ORA_SID}, Not enough arguments passed" exit 1

fi }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_bkup_dir(): Create backup directories if not already exist #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_bkup_dir() {

EXPORT_DIR=${BACKUPDIR}

if [ ! -d ${EXPORT_DIR} ]; then mkdir -p ${EXPORT_DIR}; fi if [ ! -d ${DYN_DIR} ]; then mkdir -p ${DYN_DIR}; fi

if [ ! -d ${LOGDIR} ]; then mkdir -p ${LOGDIR}; fi FILE="${EXPORT_DIR}/${ORA_SID}.dmp"

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_get_vars(): Get environment variables

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_get_vars(){

ORA_HOME=´sed /#/d ${ORATABDIR}|grep -i ${ORA_SID}|nawk -F ":" '{print $2}'´ ORA_BASE=´echo ${ORA_HOME}|nawk -F "/" '{for (i=2; i<=NF-2; i++)

print "/"$i}'´

ORACLE_BASE=´echo $ORA_BASE|tr -d " "´ ORACLE_HOME=${ORA_HOME}; export ORACLE_HOME ORACLE_SID=${ORA_SID}; export ORACLE_SID #CON_STRING=${ORA_SID}.company.com

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_unix_command_status(): Check exit status of Unix command #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_unix_command_status() {

if [ $? != 0 ]; then

echo "´date´" >> ${LOGDIR}/${ORA_SID}.log

echo "EXPORT_FAIL: ${1} " >> ${LOGDIR}/${ORA_SID}.log exit 1 fi } ###################################### # MAIN ###################################### NARG=$# ORA_SID=$1 ORA_OWNER=$2

# Set up the environment

BACKUPDIR="/u02/${ORA_SID}/export" ORATABDIR=/etc/oratab

(24)

TOOLS="/u01/oracomn/admin/my_dba"

DYN_DIR="${TOOLS}/DYN_FILES" PARFILE="${DYN_DIR}/export.par" LOGDIR="${TOOLS}/localog"

echo "... Now exporting .... ${ORA_SID}" funct_chk_parm funct_get_vars funct_verify funct_chk_bkup_dir funct_build_parfile funct_export funct_cleanup

echo ´date´ >> $LOGDIR/${ORA_SID}.log

echo "${ORA_SID}, export completed successfully" >> $LOGDIR/${ORA_SID}.log ####################### END MAIN ###############################

Export Script under Unix Checklist

In the main function, set the correct values for BACKUPDIR, ORATABDIR, and TOOLS

variables highlighted in the export script. The default location of ORATABDIR is different for

each flavor of Unix.

Check for existence of SID in the oratab file. If not already there, you must add the

instance.

The funct_build_parfile() function builds the parameter file. By default, it performs a

full export. You can modify the parameters to perform a user- or table-level export.

Pass SID and OWNER as parameters to the program:

• funct_build_parfile() Builds the export.par parameter file dynamically, based on the

information provided in this function. This function is configured for a full export of the

database. To perform a different type of export (user- or table-level), set the correct

parameters.

• funct_cleanup() Removes the interim files.

Export Troubleshooting and Status Check

The 'Log' parameter value set in the parameter file will have detailed information about the status

of export. This is a very good place to start investigating why an export has failed or for related

errors.

A single line about the success or failure of export is appended to SID.log file every time an export

is performed. This file is located under the directory defined by the LOGDIR variable. This file also

has the backup completion time. A separate file is created for each instance. This single file

maintains the history of performed backups, their status, and timing information. The messages for

an export are 'EXPORT_FAIL', if the export failed, and 'Export Completed successfully', if the

export completes successfully.

The following is an excerpt from a log file:

Tue Apr 8 16:07:12 EST 2000

(25)

Split Export

The split export program (see Listing 3.6) performs an export of the database. Additionally, if the

export file is larger than 2GB, the script compresses the export file and splits into multiple files to

overcome the export limitation of a 2GB file system size. This is the only way to split the export

file prior to Oracle 8i. New features in 8I allow you to split the export file into multiple files, but it

does not compress the files on-the-fly to save space. The script uses the Unix commands split

and compress to perform splitting and compressing of the files. The functions of the script are

explained in

Figure 3.5

.

The split export script takes two input parameters—SID and OWNER. SID is the instance to be

backed up, and OWNER is the Unix account under which Oracle is running.

Export New Features in 8i

In 8i, Oracle introduced two new export parameters called FILESIZE and QUERY. FILESIZE

specifies the maximum file size of each dump file. This overcomes the 2GB file system limitations

of export command operating systems. By using the QUERY parameter, you can export the subset of

a table data. During an import, when using split export files, you have to specify the same

FILESIZE limit.

Listing 3.6

splitZxport_ux

###################################################################### # PROGRAM NAME: splitZxport_ux

#

# PURPOSE: Performs export of the database

# Compresses the export file on the fly while splitting. # Useful if the size of export file goes beyond 2GB

# USAGE: $splitZxport_ux SID OWNER

# INPUT PARAMETERS: SID(Instance name), OWNER(Owner of instance)

###################################################################### #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_verify(): Verify that database is online

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_verify(){

STATUS=´ps -fu ${ORA_OWNER} |grep -v grep| grep ora_pmon_${ORA_SID}´ funct_chk_unix_command_status "Database is down for given SID($ORA_SID), Owner($ORA_OWNER). Can't perform export "

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_cleanup(): Cleanup interim files

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_cleanup() { rm –f ${PIPE_DEVICE} rm –f ${SPLIT_PIPE_DEVICE} } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_splitcompress_pipe(): Creates pipe for compressing and splitting of file

(26)

funct_splitcompress_pipe() { # Creates pipe for compressing

if [ ! -r ${PIPE_DEVICE} ]; then /etc/mknod ${PIPE_DEVICE} p

fi

#Creates pipe for splitting

if [ ! -r ${SPLIT_PIPE_DEVICE} ]; then /etc/mknod ${SPLIT_PIPE_DEVICE} p

fi

# Splits the file for every 500MB

# As it splits it adds aa,bb,cc ... zz to the name

nohup split -b1000m - ${ZFILE} < ${SPLIT_PIPE_DEVICE} & nohup compress < ${PIPE_DEVICE} >${SPLIT_PIPE_DEVICE} & }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_build_parfile(): Creates parameter file

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_build_parfile() {

# This line makes sure that it always creates a new parameter file echo " " >${PARFILE} echo "userid=system/manager">>${PARFILE} echo "Full=Y">>${PARFILE} #echo "tables=scott.t1">>${PARFILE} echo "Grants=Y">>${PARFILE} echo "Indexes=Y">>${PARFILE} echo "Rows=Y">>${PARFILE} echo "Constraints=Y">>${PARFILE} echo "Compress=N">>${PARFILE} echo "Consistent=Y">>${PARFILE} echo "File=${PIPE_DEVICE}">>${PARFILE} echo "Log=${EXPORT_DIR}/${ORA_SID}.exp.log">>${PARFILE} } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_export(): Export the database

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_export() {

# Remove old export file rm -f ${ZFILE}

${ORACLE_HOME}/bin/exp parfile=${PARFILE} if [ $? != 0 ]; then

echo ´date´ >> $LOGDIR/${ORA_SID}.log

echo "EXPORT_FAIL: ${ORA_SID}, Export Failed" >> $LOGDIR/${ORA_SID}.log funct_cleanup

exit 1 fi

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_parm(): Check for input parameters

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_parm() {

if [ ${NARG} -ne 2 ]; then

echo "EXPORT_FAIL: ${ORA_SID}, Not enough arguments passed" exit 1

(27)

fi }

#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

# funct_chk_bkup_dir(): Create backup directories if not already existing #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

funct_chk_bkup_dir() { EXPORT_DIR=${BACKUPDIR}

if [ ! -d ${EXPORT_DIR} ]; then mkdir -p ${EXPORT_DIR}; fi if [ ! -d ${DYN_DIR} ]; then mkdir -p ${DYN_DIR}; fi

if [ ! -d ${LOGDIR} ]; then mkdir -p ${LOGDIR}; fi ZFILE="${EXPORT_DIR}/${ORA_SID}.dmp.Z"

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_get_vars(): Get environment variables

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_get_vars(){

ORA_HOME=´sed /#/d ${ORATABDIR}|grep -i ${ORA_SID}|nawk -F ":" '{print $2}'´ ORA_BASE=´echo ${ORA_HOME}|nawk -F "/" '{for (i=2; i<=NF-2; i++)

print "/"$i}'´

ORACLE_BASE=´echo $ORA_BASE|tr -d " "´ ORACLE_HOME=${ORA_HOME}; export ORACLE_HOME ORACLE_SID=${ORA_SID}; export ORACLE_SID }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_unix_command_status(): Check exit status of Unix command #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_unix_command_status() {

if [ $? != 0 ]; then

echo "´date´" >> ${LOGDIR}/${ORA_SID}.log

echo "EXPORT_FAIL: ${1} " >> ${LOGDIR}/${ORA_SID}.log exit 1 fi } ####################################### ## MAIN ####################################### NARG=$# ORA_SID=$1 ORA_OWNER=$2 # Set up environment BACKUPDIR="/u02/${ORA_SID}/export" ORATABDIR=/etc/oratab TOOLS="/u01/oracomn/admin/my_dba" DYN_DIR="${TOOLS}/DYN_FILES" PARFILE="${DYN_DIR}/export.par" LOGDIR="${TOOLS}/localog" PIPE_DEVICE="/tmp/export_${ORA_SID}_pipe" SPLIT_PIPE_DEVICE="/tmp/split_${ORA_SID}_pipe" echo "... Now exporting .... ${ORA_SID}" funct_chk_parm

(28)

funct_get_vars funct_verify funct_chk_bkup_dir funct_splitcompress_pipe funct_build_parfile funct_export funct_cleanup

echo ´date´ >> $LOGDIR/${ORA_SID}.log

echo "${ORA_SID}, export completed successfully" >> $LOGDIR/${ORA_SID}.log ####################### END MAIN ###############################

Split Export Script under Unix Checklist

The checklist of things to verify before the splitZxport is run is the same as for the export

program.

• funct_splitcompress_pipe() This function creates two pipes—one for compressing and

another for splitting. The export dump file is passed to the compress pipe for compression,

and the output of the compress command is passed to the split command for the split

operation. The output of split command is passed to a file. The split command splits the

dump file into pieces of 1000MB. When the split operation occurs, it appends aa, bb,

cc...zz to the name of the original file to maintain different names for individual pieces.

compress and split are Unix commands.

• funct_build_parfile() In building the parameter file, we pass the pipe name as a

filename to the export command. The pipe acts as a medium to transfer output from one

command to another.

Split Import

The split import program (see Listing 3.7) performs an import using the compressed split export

dump files created by the splitZxport program. The script takes two input parameters—SID and

OWNER. SID is the instance to be backed up, and OWNER is the Unix account under which Oracle is

running.

Listing 3.7

splitZmport_ux

###################################################################### # PROGRAM NAME: splitZmport_ux

# PURPOSE: Performs import of the database using export files created by #splitZxport program. Uncompresses the dump file on the fly while desplitting. # USAGE: $splitZmport_ux SID OWNER

# INPUT PARAMETERS: SID(Instance name), OWNER(Owner of instance)

###################################################################### #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_verify(): Verify that database is online

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_verify(){

STATUS=´ps -fu ${ORA_OWNER} |grep -v grep| grep ora_pmon_${ORA_SID}´ funct_chk_unix_command_status "Database is down for given SID($ORA_SID), Owner($ORA_OWNER). Can't perform impot"

(29)

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_cleanup(): Cleanup interim files

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_cleanup() { rm –f ${PIPE_DEVICE} rm –f ${SPLIT_PIPE_DEVICE} } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_desplitcompress_pipe(): Creates pipe for uncompressing and desplitting of file

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_desplitcompress_pipe() {

# Creates pipe for uncompressing if [ ! -r ${PIPE_DEVICE} ]; then /etc/mknod ${PIPE_DEVICE} p

fi

#Creates pipe for desplitting

if [ ! -r ${SPLIT_PIPE_DEVICE} ]; then /etc/mknod ${SPLIT_PIPE_DEVICE} p fi

nohup cat ${ZFILES} > ${SPLIT_PIPE_DEVICE} & sleep 5

nohup uncompress < ${SPLIT_PIPE_DEVICE} >${PIPE_DEVICE} & sleep 30

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_build_parfile(): Creates parameter file

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_build_parfile() {

# This line makes sure that it always creates a new parameter file echo " " >${PARFILE} echo "userid=system/manager">>${PARFILE} #echo "indexfile=${BACKUPDIR}/${ORA_SID}.ddl">>${PARFILE} #echo "Owner=scott">>${PARFILE} #echo "Fromuser=kishan">>${PARFILE} #echo "Touser=aravind">>${PARFILE} #echo "Tables=T1,T2,t3,t4">>${PARFILE} echo "Full=Y">>${PARFILE} echo "Ignore=Y">>${PARFILE} echo "Commit=y">>${PARFILE} echo "File=${PIPE_DEVICE}">>${PARFILE} echo "Log=${BACKUPDIR}/${ORA_SID}.imp.log">>${PARFILE} } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_import(): Import the database

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_import() {

${ORACLE_HOME}/bin/imp parfile=${PARFILE} if [ $? != 0 ]; then

echo ´date´ >> $LOGDIR/${ORA_SID}.log

echo "IMPORT_FAIL: ${ORA_SID}, Import Failed" >> $LOGDIR/${ORA_SID}.log funct_cleanup

(30)

exit 1 fi

}

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_parm(): Check for input parameters

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_parm() {

if [ ${NARG} -ne 2 ]; then

echo "IMPORT_FAIL: ${ORA_SID}, Not enough arguments passed" exit 1

fi }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_bkup_dir(): Check for backup directories

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_bkup_dir() {

if [ ! -d ${DYN_DIR} ]; then mkdir -p ${DYN_DIR}; fi if [ ! -d ${LOGDIR} ]; then mkdir -p ${LOGDIR}; fi }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_get_vars(): Get environment variables

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_get_vars(){

ORA_HOME=´sed /#/d ${ORATABDIR}|grep -i ${ORA_SID}|nawk -F ":" '{print $2}'´ ORA_BASE=´echo ${ORA_HOME}|nawk -F "/" '{for (i=2; i<=NF-2; i++)

print "/"$i}'´

ORACLE_BASE=´echo $ORA_BASE|tr -d " "´ ORACLE_HOME=${ORA_HOME}; export ORACLE_HOME ORACLE_SID=${ORA_SID}; export ORACLE_SID }

#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # funct_chk_unix_command_status(): Check exit status of Unix command #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: funct_chk_unix_command_status() {

if [ $? != 0 ]; then

echo "´date´" >> ${LOGDIR}/${ORA_SID}.log

echo "IMPORT_FAIL: ${1} " >> ${LOGDIR}/${ORA_SID}.log exit 1 fi } ####################################### ## MAIN ####################################### NARG=$# ORA_SID=$1 ORA_OWNER=$2 # Set up environment BACKUPDIR="/u02/${ORA_SID}/export" ORATABDIR=/etc/oratab TOOLS="/u01/oracomn/admin/my_dba"

(31)

# List all split files in ZFILES variable #ZFILES=´echo ${BACKUPDIR}/file.dmp.Z??|sort´ ZFILES="${BACKUPDIR}/file.dmp.Zaa ${BACKUPDIR}/file.dmp.Zab" DYN_DIR="${TOOLS}/DYN_FILES" PARFILE="${DYN_DIR}/import.par" LOGDIR="${TOOLS}/localog" PIPE_DEVICE="/tmp/import_${ORA_SID}_pipe" SPLIT_PIPE_DEVICE="/tmp/split_${ORA_SID}_pipe" NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1;export NLS_LANG echo "... Now importing .... ${ORA_SID}"

funct_chk_parm funct_get_vars funct_verify funct_chk_bkup_dir funct_desplitcompress_pipe funct_build_parfile funct_import funct_cleanup

echo ´date´ >> $LOGDIR/${ORA_SID}.log

echo "${ORA_SID}, import completed successfully" >> $LOGDIR/${ORA_SID}.log ####################### END MAIN ###############################

SplitImport Script under Unix Checklist

In the main() function, set the correct values for the BACKUPDIR, ORATABDIR, and TOOLS

variables highlighted in the import script. The default location of ORATABDIR is different for

each flavor of Unix.

Check for the existence of the SID in the oratab file. If not already there, you must add the

instance.

List all split filenames in the ZFILES variable in the main() function.

The funct_build_parfile() function builds the parameter file. By default, it performs a

full import. You can modify the settings to perform a user or table import.

Pass SID and OWNER as parameters to the program:

funct_desplitcompress_pipe() The only trick here is that we need to split and uncompress

the files before we use them as input to import command. That is accomplished by creating two

pipes. Here, we use the cat command to send output from split files to the split pipe device. The

split pipe device is passed to the uncompress command. The output from the uncompress

command is sent to the Oracle import command. cat and uncompress are Unix commands.

Everything else is the same as a regular import.

Oracle Software Backup

This section discusses backing up the software directories of Oracle. We have already discussed

how to back up the database. Backing up software is also a very important part of a backup

strategy. The software might not need to be backed up as often as the database because it does not

change quite as often. But as you upgrade, or before you apply any patches to existing software, it

is important to make a backup copy of it to avoid getting into trouble.

References

Related documents

A full backup is an operating system backup of all data files, on-line redo log files and control file that constitute ORACLE database and the parameter.. Can a View based on

 BRBACKUP calls BACKINT with –f backup –t volume and a list of all database files in the input file (for an offline backup the list would also contain the online redo log files

Since the database files change while the backup copy is being made, one needs all log files that were active at the beginning of the backup, and all log files produced during

A closed database (cold) backup is an operating system backup of all data files, control files, redo log files, parameter files, and the password file that constitute an

Một redo log được tạo thành từ nhiều redo entries (gọi là các redo records). Chức năng chính của redo log là ghi lại tất cả các thay đổi đối với dữ

Restore all data files (including system, data, index, undo but not control file or redo log files).. RECOVER DATABASE UNTIL TIME ‘dd-mon-yyyy hh24:mi:ss’ (or CANCEL or

• Before you create an Oracle database, decide how to protect the database against potential media failures. If you do not develop a backup strategy before creating your database,

This means that as the redo logs become full, the database will hang until the DBA issues the ARCHIVE LOG ALL command, which archives all the online redo log files not yet