| Steve Rea's Oracle and SunGardHE Banner Tips, Tricks, and Scripts Back to Home |
Contents:
Backups Using RMAN
(includes
rmanbackup.shl
and
rmancrosscheck.shl
scripts)
Cleaning Out
the RMAN Backup Directory and Archivelogs
Cloning Using RMAN
(includes
rmanclone.shl
script)
Cloning Using RMAN on Windows
Cloning Using RMAN across servers
Restoring a Database from an
RMAN Backup
Creating a Data Guard Standby Database Using RMAN
Recreating a Data
Guard Standby Database Using RMAN
Creating a Local Data Guard Standby Database on Windows (added 5/30/10)
RMAN (Recovery Manager) is Oracle's backup and recovery tool, which is included with your Oracle database (8.0 and above). You don't have to install anything to use it, and, there is very little, if anything, that you have to set up to get it going (although there are a lot of things you can configure when you get further into RMAN). You do have to be logged into your oracle user ID on your UNIX server containing the database (we are on AIX 5.2 and 5.3 servers with Oracle 10.2.0.3 databases), and you do have to have your ORACLE_SID set to the database you want to work with (which RMAN calls the "target" database), but, other than that, you can do something as simple as the following to back up your database while it is running, assuming you are in ARCHIVELOG mode:
rman target /
backup database;
exit;
The above "backup database" command backs up your datafiles, control file, and server parameter file (if you have one, but not your init.ora file). If you also want to back up your archive logs, you would change that command to "backup database plus archivelog;" RMAN also lets you back up individual types of files separately, such as just the archivelogs, or your control file, or your server parameter file, or even individual tablespaces or datafiles.
The default directory that RMAN puts these backups into is $ORACLE_HOME/dbs in UNIX (or %ORACLE_HOME%/database in Windows, but, I'll just be using UNIX here). You can tell RMAN to put them somewhere else that you can manage manually, or even set up a "Flash Recovery Area" (FRA) and let Oracle manage the backups and archivelogs for you (such as automatically deleting old backups). And, you can set up a "Recovery Catalog" to contain RMAN backup information about all of your databases in one central location (which is in addition to this information being stored in the database's control file). But, let's keep it simple for now, and use the default backup directory without a recovery catalog. (See the end of "Creating a Data Guard Standby Database Using RMAN" on how to create an RMAN backup to a "different" Oracle Home that is defined on another server.)
The first time you try to do an RMAN backup of your archive logs, you will probably get "RMAN-06059: expected archived log not found, lost of archived log compromises recoverability" (yes, that is an Oracle spelling error - it says "lost" instead of "loss"!) and "ORA-19625: error identifying file ..." with the file name of one of your archive logs (and other messages with these). This happens when you've deleted your old archive logs from disk, but, entries for them still exist in your database. To tell RMAN to ignore those missing archive logs, you will run the following "crosscheck" command, and, after that, you can run the "backup database plus archivelog;" command again:
rman target /
crosscheck archivelog all;
exit;
If your database is in NOARCHIVELOG mode, you can restart it in the mount state and back it up:
rman target /
startup force mount
backup database;
alter database open;
exit;
Instead of trying to remember which databases we have on our system to back up, and whether they are in ARCHIVELOG mode or in NOARCHIVELOG mode, and which ones need to be shut down to make an RMAN backup, and what commands to enter to back up the datafiles and control files and server parameter files and archive logs, and how to tag those backups so that we know what's in them at a glance, why not just create a script to figure out all of this stuff for us? And, while we're at it, let's have it back up whichever SID's we want at the time, or a predefined list of SID's, or even all SID's listed in the /etc/oratab file, and have it do either full backups or incremental backups either as we specify or based on the day of the week (incremental backups on weekdays, full backups on weekends). Well, here it is:
Script: rmanbackup.shl
Performs an RMAN backup of the current database SID, or the given database SID's, or a pre-defined list of database SID's, or all of the SID's listed in /etc/oratab. The backup can either be a full backup (incremental level=0) or an incremental (differential level=1) backup. If no parameters are specified, a full backup of the current $ORACLE_SID is done. Otherwise, the parameters consist of the list of SID's to be backed up and/or any of the following:
LIST - include the pre-defined list (bkup_list) of SID's.
ORATAB - include all SID's listed in the /etc/oratab file.
FULL - make a full backup of all of the SID's that are listed.
INCR - make an incremental (level=1) backup of all SID's listed.
If the type of backup is not specified, and no specific SID's are given (just LIST or ORATAB), an incremental backup is done Monday through Thursday or a full backup is done Friday through Sunday (assuming nightly backups). The pre-defined list of SID's for the "LIST" backup is specified in the "bkup_list" variable shown below (edit the "export bkup_list" line in this script to match your environment):
export bkup_list='PROD PPRD TEST'
Databases that are currently down will not be backed up, since they must be at least in the mount state for RMAN to connect to them. Databases in NOARCHIVELOG mode will be shut down and started back up in the mount state to do their backup. Databases in ARCHIVELOG mode will be backed up online. RMAN configuration settings (default device type, compression, parallelism, autobackup, etc.) are given in the rmanbackup.config file (rename rmanbackup.config.txt to rmanbackup.config after you download it - some browsers can't download ".config" files), which is run at the beginning of the RMAN backup session, for example (edit this configuration file to match your needs):
configure default device type to disk;
configure device type disk backup type to compressed backupset parallelism 2;
configure retention policy to recovery window of 35 days;
# configure controlfile autobackup on;
What those "configure" commands say is that I'm making a disk backup, that I am running two backups in parallel (Oracle decides which datafiles, etc., go into each backup file ("backup piece")) and am doing a compressed backup (which takes more time but saves a lot of disk space), and that I'm keeping the backups around for 35 days (5 weeks) in case I need to recover from them (after which time they are marked as "OBSOLETE" and subject to deletion). Note in all of this that I haven't said anything about "channels", if you've heard the term in regards to RMAN. That's because RMAN can allocate them behind the scenes for you, and you don't have to specify them. For example, in the above configure commands, the "parallelism 2" value tells RMAN to allocate 2 channels for the backup. (The "configure" commands and auto channel allocation are in Oracle 9i and above.)
Note: In this backup script, I'm doing the datafile, archivelog, spfile, and controlfile backups separately so that I can add tags to them; otherwise, only the datafile backupset will be tagged. This also lets me archive the current log file after the datafile backups to get the most current set of archive logs. Also note that this script deletes archivelogs more than a week old which have been backed up at least 5 times. Delete that line ("delete noprompt archivelog ...") or change it as desired in this script to match your needs. (Note: I'm not using "delete obsolete" to delete the backups, because "report obsolete" shows additional files that I don't want deleted, including server parameter file backups done recently within the retention policy window. Also, I removed the deletion of backups older than 36 days (the retention policy) from the script because the deletion command ignored the "keep" settings for the backups.) If you delete any of the archive logs or backup files using an O/S command, be sure to run rmancrosscheck.shl (below) before you run an RMAN backup.
Examples:
To make a full backup of the current $ORACLE_SID:
rmanbackup.shl
rmanbackup.shl full
To make an incremental backup of the current $ORACLE_SID:
rmanbackup.shl incr
To make a full backup of a given database SID, such as PROD:
rmanbackup.shl prod
rmanbackup.shl prod full
To make an incremental backup of a given database SID, such
as PROD:
rmanbackup.shl prod incr
To make a full backup of the pre-defined list (bkup_list) of
SID's:
rmanbackup.shl list full
To make an incremental backup of the pre-defined list of
SID's:
rmanbackup.shl list incr
To make a full or incremental backup of the pre-defined list
of SID's based on the current day of the week:
rmanbackup.shl list
To make a full backup of PROD and PREP:
rmanbackup.shl prod prep full
To make a full backup of the pre-defined list of SID's, plus
SEED
rmanbackup.shl list seed full
To make a full backup of the SID's listed in /etc/oratab:
rmanbackup.shl oratab full
To make a full or incremental backup of the /etc/oratab SID's
based on the current day of the week:
rmanbackup.shl oratab
Pretty cool, huh? OK, now that we have a full RMAN backup, what can we do with it? Well, besides recovering the database in case of a hardware crash or file corruption or someone accidentally (or on purpose) deleting data or even the datafiles themselves or other disasters that you may encounter (which we will discuss later on), how about things like cloning the production database to create a test database, or using the backup to create a standby database for your production database on another site? RMAN can do this for you.
Script: rmancrosscheck.shl
Performs a crosscheck on all control files, RMAN backups, and archivelogs for all of the active databases on this server so that any of them that were manually deleted (through an O/S command) don't cause any errors in the RMAN backups. This should be run before the rmanbackup.shl script.
Usage:
rmancrosscheck.shl
Cleaning Out the RMAN Backup Directory and Archivelogs
You need to monitor the directory that you store the RMAN backups in (which is usually $ORACLE_HOME/dbs on UNIX systems) to make sure that you don't fill up the drive. Below is how I monitor our /pgms directory, which contains the RMAN backups, and how to delete the old backups there. Be sure to run rmancrosscheck.shl (above) after you delete any RMAN backups for your databases.
See how much free space (the %Used column) is in the /pgms
directory (which contains the RMAN backups):
login oracle
df -k | egrep '(pgms|used)'
If this shows /pgms is over 90% used, remove RMAN backups older than 10 days:
First, list what will be deleted (this should only include files with names like
PROD_r2ke8s6m_1_1_dbf):
cd $ORACLE_HOME/dbs
find . \( -name '*_1_1' -o -name '*_1_1_dbf' -o -name
'*_1_1_spf' -o -name '*_1_1_ctl' -o -name '*_1_1_arc' \) -mtime +10 -exec ls -ltr
{} \;
To delete all those listed above:
find . \( -name '*_1_1' -o -name '*_1_1_dbf' -o -name
'*_1_1_spf' -o -name '*_1_1_ctl' -o -name '*_1_1_arc' \) -mtime +10 -exec rm {}
\;
Or, exclude some files to delete, such as not deleting files in subdirectories
(grep -v '^...*/'):
find . \( -name '*_1_1' -o -name '*_1_1_dbf' -o -name
'*_1_1_spf' -o -name '*_1_1_ctl' -o -name '*_1_1_arc' \) -mtime +10 | grep -v
'^...*/' | sed 's/^/rm /' | sh
See the resulting free space in /pgms:
df -k | egrep '(pgms|used)'
Also, you need to monitor the archivelogs directories for all of your databases on your server, and delete any old archivelogs if they are about to fill up your drive. Below is how I monitor our /orcl directory, which contains the archivelogs for all of the databases. Be sure to run rmancrosscheck.shl (above) after you delete any of the archive logs for your databases.
See how much free space is in the /orcl directory (which
contains the archivelogs):
login oracle
df -k | egrep '(orcl|used)'
Find what archivelog directories are on this server, and how many archivelog
files are in them:
find /orcl/oradata -name archivelogs | sed 's/.*/echo & `ls &
\| wc -l`/' | sh
If the /orcl directory fills up, the databases will stop until some room is
freed up on /orcl for those archivelogs (users may get the error message:
"ORA-00257: archiver error. Connect internal only, until freed."). The
remove_old_logs.shl script in each of the
archivelogs directories (such as in /orcl/oradata/PROD/archivelogs) will remove
archivelogs older than the given number of days (be sure to change to the
appropriate archivelogs directory before running the script). Below is an
example of removing all but the last 4 days of archivelogs for the PROD
database:
cd /orcl/oradata/PROD/archivelogs
ls -ltr
remove_old_logs.shl
4
The script below will generate and execute the above commands for all databases
with more than 10 archivelog files:
find /orcl/oradata -name archivelogs | sed 's/.*/echo & `ls &
\| wc -l`/' | sh |
sed 's/\(.*\) \(.*\)/if [ \2 -gt 10
]; then~cd \1~ls -ltr~remove_old_logs.shl <<EOF~4~EOF~fi/' |
tr '~' '\n' | sh
See the results from the deletions:
find /orcl/oradata -name archivelogs | sed 's/.*/echo & `ls &
\| wc -l`/' | sh
df -k | egrep '(orcl|ndxs|used)'
NOTE: After removing backups and/or archivelogs and before doing another RMAN backup, run rmancrosscheck.shl (above) to tell RMAN that those files are no longer available. This script is also scheduled to run right before the nightly RMAN backups on our database servers.
To clone a database, RMAN not only needs to connect to the database being cloned, such as your production database (PROD), but also to the database being created, such as your test database (TEST) (which RMAN calls the "auxiliary" database). But, wait a minute! If the test database hasn't been created, how do I connect to it?! Actually, the test database just needs to be in the nomount state, which means that just a parameter file (init<SID>.ora file) or a server parameter file (spfile<SID>.ora) needs to exist in the $ORACLE_HOME/dbs directory for the test database. Also, an entry for the test database must exist in the /etc/oratab file. Finally, for RMAN to connect to the databases, entries for them must exist in the $ORACLE_HOME/network/admin/tnsnames.ora file.
But, we have to take care of one other detail. We've copied the initPROD.ora file to the initTEST.ora file and changed the locations of the control files, the dump, audit, and archivelog directories, and the db_name parameter, for the test database in initTEST.ora; but, the datafile and archivelog names for the test database also have to be different than the production database. Well, that's where the init.ora parameters db_file_name_convert and log_file_name_convert come into play (if you've created a standby database, you'll recognize these parameters). If you define those in the initTEST.ora file as shown below, RMAN will change all occurrences of "PROD" in the datafile and log file names to "TEST" for the clone:
db_file_name_convert=('PROD','TEST')
log_file_name_convert=('PROD','TEST')
Then, after starting up the test database in nomount mode, you can do something as simple as the following to clone your production database while it is running:
rman target / auxiliary sys/<test_sys_password>@myserver_test
duplicate target database to TEST;
exit
If you've already cloned to TEST before, you will need to delete the TEST database's files before you do the clone again. RMAN can do that for you, too, using the "drop database including backups;" command when the TEST database is in a mount state. But, make sure you are dropping TEST, not PROD! Note that this will also delete your server parameter file for TEST, so, if you are using spfile's, you will need to create a parameter file (initTEST.ora) before dropping TEST, and then recreate the server parameter file after the drop.
OK, that's a lot to remember and check as well. So, here we go with another script, which checks to make sure that the /etc/oratab entries exist, that the parameter files exist, and that the tnsnames.ora entries exist, then, it creates a pfile from the spfile if one exists, drops the clone database if it exists (Oracle 10g), creates a new spfile and sets up the file_name_convert parameters, and runs the duplicate command. And, to top it off, for the Banner folks, it also updates the gubinst fields to reflect the clone and date. Here it is:
Script: rmanclone.shl
Performs an RMAN clone of one database SID to another
database SID up to an optional point-in-time or up to the current point-in-time.
The RMAN database backup(s) of the source SID must be available on-line, as well
as sufficient archive logs to recover up to the desired point-in-time.
Usage:
rmanclone.shl <from SID> <to SID> <MM/DD/YY:HH/MI/SS>
where the "as of" date and time is optional (default is now).
Prerequisites: The target SID's init.ora file or spfile.ora file must already exist. The
target SID's init.ora file, if any, is saved off, and an spfile is created for
the target. Also, the connect string for the source and the target is
assumed to be in the form of "<server>_<sid>", such as myserver_prod and
myserver_test (edit the "export rman_server=myserver" line
in this script to match your environment), and those source and target entries must exist in the $ORACLE_HOME/network/admin/tnsnames.ora
file. The source and target SID's must also be in the /etc/oratab file.
And, you have to be logged into the oracle user ID on your UNIX database server.
Examples:
To clone PROD to TEST as of now:
rmanclone.shl PROD TEST
To clone PROD to TEST as of midnight:
rmanclone.shl PROD TEST `date
+"%D:00:00:00"`
For those of you with Oracle databases on Windows, I don't have any Windows batch scripts, but, below is what I did to clone a Windows database (from PROD to TEST) using RMAN. You will need to change the names and values (such as myserver, myschool, syspassword), along with the pathnames (such as d:\oracle\v9206, which is my ORACLE_HOME) to match your environment. This was on Oracle 9.2.0.6. Note that 9.2.0.6 doesn't have a "backup type to compressed backupset" option on its "configure device type disk" command. The commands below are run in an MS/DOS command prompt window.
Create the parameter file (initTEST.ora) for the test
clone database (TEST) from a copy of PROD's parameter file:
copy d:\oracle\v9206\database\initPROD.ora
d:\oracle\v9206\database\initTEST.ora
Edit d:\oracle\v9206\database\initTEST.ora
change all occurrences of PROD to
TEST
Add the myserver_test connect string to
d:\oracle\v9206\network\admin\tnsnames.ora:
myserver_test =
(DESCRIPTION =
(ADDRESS_LIST
=
(ADDRESS = (PROTOCOL = TCP)(Host = myserver.myschool.edu)(Port = 1521))
)
(CONNECT_DATA
= (SID = test)
)
)
Add entries for PROD (if needed) and TEST to the SID_LIST
section of d:\oracle\v9206\network\admin\listener.ora:
SID_LIST_LISTENER=
(SID_LIST=
(SID_DESC=
(SID_NAME=PROD)
(ORACLE_HOME = d:\oracle\v9206)
)
(SID_DESC=
(SID_NAME=TEST)
(ORACLE_HOME = d:\oracle\v9206)
)
)
Reload the listener to pick up the above additions:
set oracle_home=d:\oracle\v9206
set oracle_sid=prod
lsnrctl reload
Create the directories for the TEST database:
sqlplus "sys/<syspassword> as sysdba"
set heading off echo off feedback off
trimspool on
select distinct 'mkdir ' ||
replace(substr(file_name,1,
instr(file_name,'\',-1)-1),'PROD','TEST')
from
dba_data_files
union
select distinct 'mkdir ' ||
replace(substr(file_name,1,
instr(file_name,'\',-1)-1),'PROD','TEST')
from
dba_temp_files
union
select distinct 'mkdir ' ||
replace(value,'PROD','TEST')
from
v$parameter where name in ('background_dump_dest','user_dump_dest',
'core_dump_dest','audit_file_dest','log_archive_dest')
and value is
not null
union
select distinct 'mkdir ' ||
replace(substr(substr(value,instr(value,'LOCATION=')+9),1,
instr(substr(value,instr(value,'LOCATION=')+9),' ')-1),'PROD','TEST')
from
v$parameter where name between 'log_archive_dest_1' and
'log_archive_dest_10' and instr(value,'LOCATION=') > 0;
exit
Run the resulting mkdir commands from the above SQL:
mkdir D:\ORADATA\TEST
mkdir c:\oradata\TEST\archivelogs
mkdir d:\oradata\TEST\bdump
mkdir d:\oradata\TEST\cdump
mkdir d:\oradata\TEST\udump
Create the NT services for the TEST Oracle instance using
oradim:
set oracle_sid=test
oradim -new -sid test -intpwd <syspassword> -startmode auto -pfile
d:\oracle\v9206\database\initTEST.ora
Create a server parameter file for TEST and add the
file_name_convert parameters for the cloning process:
sqlplus "sys/<syspassword> as sysdba"
startup force nomount
create spfile from pfile;
startup force nomount
alter system set db_file_name_convert='PROD','TEST'
scope=spfile;
alter system set
log_file_name_convert='PROD','TEST' scope=spfile;
shutdown
exit
oradim -delete -sid test
del d:\oracle\v9206\database\pwdtest.ora
move d:\oracle\v9206\database\initTEST.ora
d:\oracle\v9206\database\initTEST.ora.save
oradim -new -sid test -intpwd <syspassword> -startmode auto -spfile
sqlplus "sys/<syspassword> as sysdba"
startup nomount
column name format a25
column value format a50
select name,value from v$parameter
where name like '%file_name_convert';
exit
Create an RMAN backup of the PROD database and clone it to
TEST:
set oracle_sid=prod
rman target sys/<syspassword>@myserver_prod auxiliary sys/<syspassword>@myserver_test
configure default device type to
disk;
configure device type disk
parallelism 2;
configure retention policy to
recovery window of 35 days;
crosscheck archivelog all;
backup database plus archivelog;
duplicate target database to TEST;
exit
Create an RMAN backup of the new TEST database:
set oracle_sid=test
rman target sys/<syspassword>@myserver_test
configure default device type to
disk;
configure device type disk
parallelism 2;
configure retention policy to
recovery window of 35 days;
backup database plus archivelog;
exit
Cloning Using RMAN across servers
If you want to create a clone of one database on one server to another server using RMAN, you will have to copy or FTP the RMAN backup files from the original database server to the new database server. Unfortunately, RMAN can't access backup files on another server, even though it can connect to a database on another server. You could use the same procedure to copy a database from one server to another (just leave out changing the SID names and file names). This should be faster than export/import. Below are my notes on how I did this, when I created a clone of PROD on PrimaryServer to XXXX on StandbyServer. This was done on 5/4/09 at 22:42:56 - you will have to change the dates here to your values. Note that this assumes that the directory structure on StandbyServer is the same as the directory structure on PrimaryServer.
THESE STEPS ARE DONE ON PrimaryServer:
Create a full backup of PROD, which will have to be FTP'ed
to StandbyServer:
login oracle
PROD
rmanbackup.shl PROD full
Create the clone's init.ora file from PROD (note: if you
had already created a clone earlier, and you are just re-creating the clone now,
some of these steps that you've already done can be left out):
cd $ORACLE_HOME/dbs
sqlplus "/ as sysdba"
create pfile='initXXXX.ora' from
spfile;
exit
vi initXXXX.ora
:1,$s/PROD/XXXX/g
:wq
Get the list of backup files from today to FTP to
StandbyServer:
find $ORACLE_HOME/dbs \( -name '*_1_1' -o -name '*_1_1_dbf'
-o -name '*_1_1_spf' -o -name '*_1_1_ctl' -o -name '*_1_1_arc' \) |
sed 's/^/ls -ltr /' | sh | grep ' May
04 22' | grep PROD | sed 's/.\{58\}/get /'
shows:
get /pgms/oracle/product/v10203/dbs/PROD_qeke7d00_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_qdke7d00_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_qfke7d9k_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qgke7d9m_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qhke7dd8_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qjke7de6_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qike7de6_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qkke7dem_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qlke7den_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qnke7df6_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qmke7df6_1_1_spf
get /pgms/oracle/product/v10203/dbs/PROD_qoke7dfl_1_1_ctl
Generate the commands to remove and create the directories
for the XXXX database (the remove commands are used in the case where an XXXX
database had been created before):
sqlplus "/ as sysdba"
set heading off feedback off
spool makedirs.shl
select distinct ' rm -r ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_data_files
union
select distinct ' rm -r ' ||
substr(substr(value,instr(value,'LOCATION=')+9),1,
instr(substr(value,instr(value,'LOCATION=')+9),' ')-13)
from
v$parameter where name between 'log_archive_dest_1' and
'log_archive_dest_10' and instr(value,'LOCATION=') > 0
union
select distinct ' rm -r ' ||
substr(value,1,instr(value,'/',-1)-1) from v$parameter
where name in
('background_dump_dest','user_dump_dest','core_dump_dest',
'audit_file_dest','log_archive_dest')
and value is
not null
union
select distinct 'mkdir -p ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_data_files
union
select distinct 'mkdir -p ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_temp_files
union
select distinct 'mkdir -p ' || value
from v$parameter
where name in
('background_dump_dest','user_dump_dest','core_dump_dest',
'audit_file_dest','log_archive_dest')
and value is
not null
union
select distinct 'mkdir -p ' ||
substr(substr(value,instr(value,'LOCATION=')+9),1,
instr(substr(value,instr(value,'LOCATION=')+9),' ')-1)
from
v$parameter where name between 'log_archive_dest_1' and
'log_archive_dest_10' and instr(value,'LOCATION=') > 0;
spool off
exit
vi makedirs.shl
:1,$s/PROD/XXXX/g
:wq
cat makedirs.shl
shows (along with the SQL above,
which can be deleted from makedirs.shl):
rm -r /data/oradata/XXXX
rm -r /ndxs/oradata/XXXX
rm -r /orcl/oradata/XXXX
rm -r /pgms/oradata/XXXX
mkdir -p
/data/oradata/XXXX
mkdir -p /ndxs/oradata/XXXX
mkdir -p /orcl/oradata/XXXX/archivelogs
mkdir -p /pgms/oradata/XXXX/audit
mkdir -p /pgms/oradata/XXXX/bdump
mkdir -p /pgms/oradata/XXXX/cdump
mkdir -p /pgms/oradata/XXXX/udump
THESE STEPS ARE DONE ON StandbyServer:
Add the clone's entry to the oratab file on StandbyServer:
login oracle
XXXX
vi /etc/oratab
add: XXXX:/pgms/oracle/product/v10203:N
:wq
Add the clone's entry to the tnsnames file:
vi $ORACLE_HOME/network/admin/tnsnames.ora
add:
StandbyServer_xxxx =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = TCP)
(Host = StandbyServer.uaex.edu)
(Port = 1521)
)
)
(CONNECT_DATA = (SID = XXXX)
)
)
Add the clone's entry to the listener.ora file:
vi $ORACLE_HOME/network/admin/listener.ora
add:
(SID_DESC=
(SID_NAME=XXXX)
(ORACLE_HOME=/pgms/oracle/product/v10203)
)
:wq
Then, reload the listener:
lsnrctl reload
FTP the init.ora file, makedirs.shl file, and the backup
files from PrimaryServer to StandbyServer:
cd $ORACLE_HOME/dbs
ftp PrimaryServer.uaex.edu
oracle
type ascii
get /pgms/oracle/product/v10203/dbs/initXXXX.ora
get /pgms/oracle/product/v10203/dbs/makedirs.shl
type binary
get /pgms/oracle/product/v10203/dbs/PROD_qeke7d00_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_qdke7d00_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_qfke7d9k_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qgke7d9m_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qhke7dd8_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qjke7de6_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qike7de6_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qkke7dem_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qlke7den_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qnke7df6_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_qmke7df6_1_1_spf
get /pgms/oracle/product/v10203/dbs/PROD_qoke7dfl_1_1_ctl
bye
Delete and recreate the directories for the new XXXX
database on StandbyServer. Also, save off and restore the remove_old_logs.shl
and fillup.shl scripts if they exist in the archivelogs directory (these are
some local scripts that I use - you may have other scripts in your archivelogs
directory that you want to preserve a copy of):
cp -p /orcl/oradata/${ORACLE_SID}/archivelogs/remove_old_logs.shl
/home/oracle/remove_old_logs.${ORACLE_SID}.shl
cp -p /orcl/oradata/${ORACLE_SID}/archivelogs/fillup.shl
/home/oracle/fillup.${ORACLE_SID}.shl
sh $ORACLE_HOME/dbs/makedirs.shl
cp -p /home/oracle/remove_old_logs.${ORACLE_SID}.shl
/orcl/oradata/${ORACLE_SID}/archivelogs/remove_old_logs.shl
cp -p /home/oracle/fillup.${ORACLE_SID}.shl /orcl/oradata/${ORACLE_SID}/archivelogs/fillup.shl
Create the password file for the new XXXX database:
rm $ORACLE_HOME/dbs/orapwXXXX
orapwd file=$ORACLE_HOME/dbs/orapwXXXX password=<sys
password> entries=5
Find the date and time to duplicate up to:
export NLS_DATE_FORMAT='DD-MON-YY HH24:MI:SS'
rman target sys/<syspassword>@PrimaryServer_prod
list backup summary completed after "to_date('05/04/09','MM/DD/YY')";
shows that
the last full backup backup file (PROD_090504224256MONFULL_CTL) completed on
04-MAY-09 at 22:48:23
exit
Clone the PROD database to XXXX as of 05/04/09 22:49:00.
Note that the "target" database is PrimaryServer_prod on PrimaryServer, even though the
RMAN backup files are on StandbyServer.
sqlplus "/ as sysdba"
startup nomount
exit
rman target sys/<syspassword>@PrimaryServer_prod auxiliary sys/<syspassword>@StandbyServer_xxxx
<<EOF
run
{
set until time = "to_date('05/04/09:22:49:00','MM/DD/YY:HH24:MI:SS')";
duplicate target database to XXXX;
}
exit
EOF
Update the gubinst fields to reflect the clone name and
date (this is only for Banner databases - if you had any other post-cloning
changes, you would do them here):
sqlplus "/ as sysdba"
update gubinst set (gubinst_instance_name,gubinst_name)
=
(select name
|| to_char(sysdate,'MMDD'),name || ' was cloned on ' ||
to_char(sysdate,'MM/DD/YY') from v$database);
select
gubinst_instance_name,gubinst_name from gubinst;
exit
Restoring a Database from an RMAN Backup
This is how we restored TEST from last Friday's (6/19/2009) full backup.
The development database
server crashed on Wednesday morning, corrupting the /ndxs files.
login root
cd /pgms/oracle/product/v10203/dbs
Mount the backup tape contining the RMAN backup files to
restore (from full backup
done on June 19) here, and restore the June 19 TEST RMAN backup files.
cpio -itvC64 </dev/rmt0 | grep 'Jun
19 .*TEST.*_1_1_' |
sed 's/.*\/pgms/\/pgms/' >xyz
cpio -imvC64 `cat xyz | tr '\n' ' '`
</dev/rmt0
cd $ORACLE_HOME/dbs
ls -ltr | grep TEST | grep 'Jun 19'
shows:
-rw-r----- 1 oracle dba 900452352 Jun 19 00:38 TEST_2rkhu7hp_1_1_dbf
-rw-r----- 1 oracle dba 1605632 Jun 19 00:38 TEST_2tkhu8k1_1_1_dbf
-rw-r----- 1 oracle dba 98304 Jun 19 00:38 TEST_2ukhu8k5_1_1_dbf
-rw-r----- 1 oracle dba 994357248 Jun 19 00:38 TEST_2skhu7hp_1_1_dbf
-rw-r----- 1 oracle dba 80832512 Jun 19 00:40 TEST_30khu8ku_1_1_arc
-rw-r----- 1 oracle dba 80167936 Jun 19 00:40 TEST_2vkhu8ku_1_1_arc
-rw-r----- 1 oracle dba 77558784 Jun 19 00:41 TEST_31khu8nv_1_1_arc
-rw-r----- 1 oracle dba 98304 Jun 19 00:41 TEST_32khu8pe_1_1_spf
-rw-r----- 1 oracle dba 1605632 Jun 19 00:41 TEST_33khu8pg_1_1_ctl
Shut down the existing TEST database.
login oracle
TEST
sqlplus "/ as sysdba"
shutdown abort
exit
Delete and recreate the directories for the TEST database
on AIX. Also, save
off and restore the remove_old_logs.shl and fillup.shl scripts if they exist
in the archivelogs directory (these are some local scripts that I use - you
may have other scripts in your archivelogs directory that you want to preserve
a copy of):
cp -p /orcl/oradata/${ORACLE_SID}/archivelogs/remove_old_logs.shl
/home/oracle/remove_old_logs.${ORACLE_SID}.shl
cp -p /orcl/oradata/${ORACLE_SID}/archivelogs/fillup.shl
/home/oracle/fillup.${ORACLE_SID}.shl
rm -r /data/oradata/TEST
rm -r /ndxs/oradata/TEST
rm -r /orcl/oradata/TEST
rm -r /pgms/oradata/TEST
mkdir -p /data/oradata/TEST
mkdir -p /ndxs/oradata/TEST
mkdir -p /orcl/oradata/TEST/archivelogs
mkdir -p /pgms/oradata/TEST/audit
mkdir -p /pgms/oradata/TEST/bdump
mkdir -p /pgms/oradata/TEST/cdump
mkdir -p /pgms/oradata/TEST/udump
cp -p /home/oracle/remove_old_logs.${ORACLE_SID}.shl
/orcl/oradata/${ORACLE_SID}/archivelogs/remove_old_logs.shl
cp -p /home/oracle/fillup.${ORACLE_SID}.shl
/orcl/oradata/${ORACLE_SID}/archivelogs/fillup.shl
Restore the control file (the one produced by my rmanbackup.shl script) with a
"_ctl" suffix and an end date of June 19. Also restore the archivelogs created
during the backup. Then, restore the database up to June 19 at 12:41:21 AM.
rman target /
startup force nomount
restore controlfile from 'TEST_33khu8pg_1_1_ctl';
startup force mount
spool log to listbackupset.lst
list backupset;
spool log off
host "grep ' *[0-9][0-9]* *19-JUN-09$' listbackupset.lst";
shows:
1 3898 400381508 18-JUN-09 400382628 19-JUN-09
1 3899 400382628 19-JUN-09 400384018 19-JUN-09
1 3900 400384018 19-JUN-09 400384253 19-JUN-09
1 3901 400384253 19-JUN-09 400384260 19-JUN-09
restore archivelog from scn=400381508 until scn=400384260;
restore database until time "to_date('06/19/09:00:41:21','MM/DD/YY:HH24:MI:SS')";
The date and time is when the control file backup finished on June 19
(as shown in the restored TEST_33khu8pg_1_1_ctl file above).
exit
Recover the database and open it with the resetlogs option
(you should probably
make a full backup of the restored database after this).
sqlplus "/ as sysdba"
startup force mount
recover automatic database until cancel using backup controlfile;
CANCEL
startup force mount
alter database open resetlogs;
exit
Creating a Data Guard Standby Database Using RMAN
Creating a Data Guard standby database on StandbyServer for the primary PROD database on PrimaryServer using RMAN is similar to cloning using RMAN across servers. Below are my notes on how I did this for our production database. Note that this assumes that the directory structure on StandbyServer is the same as the directory structure on PrimaryServer (but, see at the end on how to deal with differing Oracle Homes on the two servers).
THESE STEPS ARE DONE ON PrimaryServer:
Add the new StandbyServer standby database entry to $ORACLE_HOME/network/admin/tnsnames.ora
on PrimaryServer (note: if you had already created a standby earlier, and you are
just re-creating the standby now, some of these steps that you've already done
can be left out):
login oracle
PROD
vi $ORACLE_HOME/network/admin/tnsnames.ora
add to bottom of tnsnames.ora file:
StandbyServer_prod =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(PROTOCOL = TCP)
(Host = StandbyServer.uaex.edu)
(Port = 1521)
)
)
(CONNECT_DATA = (SID = PROD)
)
)
:wq
Create a full backup of PROD, which will have to be FTP'ed
to StandbyServer:
rmanbackup.shl PROD full
If you don't already have an spfile.ora for PROD, create
the primary's and standby's spfile.ora file from PROD (don't do this if you
already have an spfile - you may wipe it out!):
cd $ORACLE_HOME/dbs
sqlplus "/ as sysdba"
create spfile from pfile;
shutdown
startup
exit
Make a copy of the primary's spfile.ora to FTP to the
standby site:
cp -p spfilePROD.ora spfilePROD.ora.standby
Add the parameters for the Data Guard settings to the
primary PROD database's spfile.ora file:
sqlplus "/ as sysdba"
alter system set db_unique_name = 'PROD_primary'
scope=spfile;
alter system set log_archive_config =
'DG_CONFIG=(PROD_primary,PROD_standby)' scope=spfile;
alter system set log_archive_dest_1 =
'LOCATION=/orcl/oradata/PROD/archivelogs MANDATORY VALID_FOR=(ALL_LOGFILES,ALL_ROLES)
DB_UNIQUE_NAME=PROD_primary' scope=spfile;
alter system set
log_archive_dest_state_1 = ENABLE scope=spfile;
alter system set log_archive_dest_2 =
'SERVICE=StandbyServer_prod LGWR SYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)
DB_UNIQUE_NAME=PROD_standby' scope=spfile;
alter system set
log_archive_dest_state_2 = ENABLE scope=spfile;
alter system set standby_archive_dest
= /orcl/oradata/PROD/archivelogs scope=spfile;
alter system set
standby_file_management = AUTO scope=spfile;
alter system set fal_server =
StandbyServer_prod scope=spfile;
alter system set fal_client =
PrimaryServer_prod scope=spfile;
exit
Create the standby's control file from PROD:
rman target /
backup current controlfile for
standby;
shows the
following file ("piece handle") was created:
/pgms/oracle/product/v10203/dbs/cikh4u15_1_1
exit
Get the list of backup files from today to FTP to
StandbyServer:
find $ORACLE_HOME/dbs \( -name '*_1_1' -o -name '*_1_1_dbf'
-o -name '*_1_1_spf' -o -name '*_1_1_ctl' -o -name '*_1_1_arc' \) |
sed 's/^/ls -ltr /' | sh | grep ' Jun
08 20' | grep PROD | sed 's/.\{58\}/get /'
shows:
get /pgms/oracle/product/v10203/dbs/PROD_bfkh3fko_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_bekh3fko_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_bgkh3fue_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bhkh3fue_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bikh3fuu_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bjkh3fuu_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bkkh3fvd_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_blkh3fve_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bmkh3fvt_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bnkh3fvt_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bokh3g0c_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bpkh3g0c_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bqkh3g0s_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_brkh3g0s_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bskh3g1c_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_btkh3g1c_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bukh3g1s_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bvkh3g1s_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_c0kh3g2d_1_1_spf
get /pgms/oracle/product/v10203/dbs/PROD_c1kh3g2f_1_1_ctl
Generate the commands to remove and create the directories
for the standby database (the remove commands are used in the case where a
standby database had been created before on StandbyServer):
sqlplus "/ as sysdba"
set heading off feedback off
spool makedirs.shl
select distinct ' rm -r ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_data_files
union
select distinct ' rm -r ' ||
substr(substr(value,instr(value,'LOCATION=')+9),1,
instr(substr(value,instr(value,'LOCATION=')+9),' ')-13)
from
v$parameter where name between 'log_archive_dest_1' and
'log_archive_dest_10' and instr(value,'LOCATION=') > 0
union
select distinct ' rm -r ' ||
substr(value,1,instr(value,'/',-1)-1) from v$parameter
where name in
('background_dump_dest','user_dump_dest','core_dump_dest',
'audit_file_dest','log_archive_dest')
and value is
not null
union
select distinct 'mkdir -p ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_data_files
union
select distinct 'mkdir -p ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_temp_files
union
select distinct 'mkdir -p ' || value
from v$parameter
where name in
('background_dump_dest','user_dump_dest','core_dump_dest',
'audit_file_dest','log_archive_dest')
and value is
not null
union
select distinct 'mkdir -p ' ||
substr(substr(value,instr(value,'LOCATION=')+9),1,
instr(substr(value,instr(value,'LOCATION=')+9),' ')-1)
from
v$parameter where name between 'log_archive_dest_1' and
'log_archive_dest_10' and instr(value,'LOCATION=') > 0;
spool off
exit
cat makedirs.shl
shows (along with the SQL above,
which can be deleted from makedirs.shl):
rm -r /data/oradata/PROD
rm -r /ndxs/oradata/PROD
rm -r /orcl/oradata/PROD
rm -r /pgms/oradata/PROD
mkdir -p
/data/oradata/PROD
mkdir -p /ndxs/oradata/PROD
mkdir -p /orcl/oradata/PROD/archivelogs
mkdir -p /pgms/oradata/PROD/audit
mkdir -p /pgms/oradata/PROD/bdump
mkdir -p /pgms/oradata/PROD/cdump
mkdir -p /pgms/oradata/PROD/udump
Generate the SQL to create the standby redo log groups for
the new StandbyServer standby database:
sqlplus "/ as sysdba"
column o1 noprint
column o2 noprint
column maxgroup new_value maxgroup
select max(group#) maxgroup from
v$logfile where type = 'ONLINE';
select group# o1,1 o2,'alter database
add standby logfile group ' ||
to_char(group#+&maxgroup)
|| ' ('
from v$log
union all
select group#,2,' ''' ||
replace(replace(member,group#,group#+&maxgroup),
'/log_','/stby_log_')
|| ''','
from
v$logfile lf1 where member not in (select max(member) from v$logfile lf2
where
lf1.group# = lf2.group#) and type = 'ONLINE'
union all
select l1.group#,3,' ''' ||
replace(replace(member,l1.group#,l1.group#+&maxgroup),
'/log_','/stby_log_')
|| ''') size ' || bytes / 1024 || 'K;'
from
v$logfile lf1,v$log l1 where lf1.group# = l1.group#
and member =
(select max(member) from v$logfile lf2 where lf1.group# = lf2.group#)
and type =
'ONLINE'
union all
select group#+1,1,'alter database add
standby logfile group ' ||
to_char(group#+1+&maxgroup)
|| ' (' from v$log
where group#
= &maxgroup
union all
select group#+1,2,' ''' ||
replace(replace(member,group#,group#+1+&maxgroup),
'/log_','/stby_log_')
|| ''',' from v$logfile lf1 where group# = &maxgroup
and member
not in (select max(member) from v$logfile lf2 where lf1.group# = lf2.group#)
and type =
'ONLINE'
union all
select l1.group#+1,3,' ''' ||
replace(replace(member,l1.group#,l1.group#+1+&maxgroup),
'/log_','/stby_log_')
|| ''') size ' || bytes / 1024 || 'K;'
from
v$logfile lf1,v$log l1 where lf1.group# = l1.group#
and l1.group#
= &maxgroup
and member =
(select max(member) from v$logfile lf2 where lf1.group# = lf2.group#)
and type =
'ONLINE'
order by
1,2,3;
exit
shows:
alter database add standby logfile group 4 (
'/orcl/oradata/PROD/stby_log_PROD_4A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_4B.rdo') size 4096K;
alter database add standby logfile group 5 (
'/orcl/oradata/PROD/stby_log_PROD_5A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_5B.rdo') size 4096K;
alter database add standby logfile group 6 (
'/orcl/oradata/PROD/stby_log_PROD_6A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_6B.rdo') size 4096K;
alter database add standby logfile group 7 (
'/orcl/oradata/PROD/stby_log_PROD_7A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_7B.rdo') size 4096K;
THESE STEPS ARE DONE ON StandbyServer:
Add the new PROD standby database entry to the oratab file
on StandbyServer and switch to it:
login oracle
(enter any existing database if it
asks for a SID)
vi /etc/oratab
add:
PROD:/pgms/oracle/product/v10203:N
:wq
. oraenv
PROD
Add the new PROD standby database entry to the
listener.ora file:
vi $ORACLE_HOME/network/admin/listener.ora
add:
(SID_DESC=
(SID_NAME=PROD)
(ORACLE_HOME=/pgms/oracle/product/v10203)
)
:wq
Then, reload the listener:
lsnrctl reload
FTP the makedirs.shl file, standby spfile.ora file,
standby control file, and the backup files from PrimaryServer to StandbyServer:
cd $ORACLE_HOME/dbs
ftp PrimaryServer.uaex.edu
oracle
type ascii
get /pgms/oracle/product/v10203/dbs/makedirs.shl
type binary
get /pgms/oracle/product/v10203/dbs/spfilePROD.ora.standby
get /pgms/oracle/product/v10203/dbs/cikh4u15_1_1
get /pgms/oracle/product/v10203/dbs/PROD_bfkh3fko_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_bekh3fko_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_bgkh3fue_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bhkh3fue_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bikh3fuu_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bjkh3fuu_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bkkh3fvd_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_blkh3fve_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bmkh3fvt_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bnkh3fvt_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bokh3g0c_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bpkh3g0c_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bqkh3g0s_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_brkh3g0s_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bskh3g1c_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_btkh3g1c_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bukh3g1s_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_bvkh3g1s_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_c0kh3g2d_1_1_spf
get /pgms/oracle/product/v10203/dbs/PROD_c1kh3g2f_1_1_ctl
bye
mv spfilePROD.ora.standby spfilePROD.ora
Delete and recreate the directories for the new PROD
database on StandbyServer. Also, save off and restore the remove_old_logs.shl
and fillup.shl scripts if they exist in the archivelogs directory (these are
some local scripts that I use - you may have other scripts in your archivelogs
directory that you want to preserve a copy of):
cp -p /orcl/oradata/${ORACLE_SID}/archivelogs/remove_old_logs.shl
/home/oracle/remove_old_logs.${ORACLE_SID}.shl
cp -p /orcl/oradata/${ORACLE_SID}/archivelogs/fillup.shl
/home/oracle/fillup.${ORACLE_SID}.shl
sh $ORACLE_HOME/dbs/makedirs.shl
cp -p /home/oracle/remove_old_logs.${ORACLE_SID}.shl
/orcl/oradata/${ORACLE_SID}/archivelogs/remove_old_logs.shl
cp -p /home/oracle/fillup.${ORACLE_SID}.shl /orcl/oradata/${ORACLE_SID}/archivelogs/fillup.shl
Create the standby's password file:
rm $ORACLE_HOME/dbs/orapwPROD
orapwd file=$ORACLE_HOME/dbs/orapwPROD password=<sys
password> entries=5
Modify the spfile parameters for the standby database:
sqlplus "/ as sysdba"
startup nomount
alter system set audit_trail='false'
scope=spfile;
alter system set db_unique_name='PROD_standby'
scope=spfile;
alter system set log_archive_config='DG_CONFIG=(PROD_primary,PROD_standby)'
scope=spfile;
alter system set
log_archive_dest_1='LOCATION=/orcl/oradata/PROD/archivelogs MANDATORY VALID_FOR=(ALL_LOGFILES,ALL_ROLES)
DB_UNIQUE_NAME=PROD_standby' scope=spfile;
alter system set
log_archive_dest_2='SERVICE=PrimaryServer_prod LGWR SYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)
DB_UNIQUE_NAME=PROD_primary' scope=spfile;
alter system set
log_archive_dest_state_2=enable scope=spfile;
alter system set fal_server='PrimaryServer_prod'
scope=spfile;
alter system set fal_client='StandbyServer_prod'
scope=spfile;
startup force nomount
exit
Create the new PROD standby database on StandbyServer from the
PROD RMAN backups from PrimaryServer:
rman target sys/<sys password>@PrimaryServer_prod auxiliary /
duplicate target database for standby
nofilenamecheck;
exit
Start up managed recovery for the new PROD standby
database on StandbyServer:
sqlplus "/ as sysdba"
alter database recover managed
standby database disconnect from session;
Note: This
creates the redo log files in /orcl/oradata/PROD.
exit
Do a log switch on the PROD primary database (you may have
to do the switch several times), and check to see that the archive logs are
coming across to the standby server:
PrimaryServer:
sqlplus "/ as sysdba"
alter system archive log current;
exit
StandbyServer:
ls -ltr /orcl/oradata/PROD/archivelogs
Add the standby log files for the new PROD standby
database on StandbyServer and start up managed recovery (note: this can't be done
until archiving has been started to the new standby from the primary by doing a
log switch):
sqlplus "/ as sysdba"
alter database recover managed
standby database cancel;
alter database open read only;
column member format a55
select vs.group#,vs.bytes,vl.member
from v$standby_log vs,v$logfile vl
where
vs.group# = vl.group# order by vs.group#,vl.member;
alter database add standby logfile
group 4 (
'/orcl/oradata/PROD/stby_log_PROD_4A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_4B.rdo')
size 4096K;
alter database add standby logfile
group 5 (
'/orcl/oradata/PROD/stby_log_PROD_5A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_5B.rdo')
size 4096K;
alter database add standby logfile
group 6 (
'/orcl/oradata/PROD/stby_log_PROD_6A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_6B.rdo')
size 4096K;
alter database add standby logfile
group 7 (
'/orcl/oradata/PROD/stby_log_PROD_7A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_7B.rdo')
size 4096K;
select vs.group#,vs.bytes,vl.member
from v$standby_log vs,v$logfile vl
where
vs.group# = vl.group# order by vs.group#,vl.member;
alter database recover managed
standby database disconnect from session;
exit
Note: If StandbyServer does not have the same directory structure as PrimaryServer, such as if the ORACLE_HOME is different between the two servers, you can "fool" RMAN into looking for the backups using the standby server's Oracle Home directory instead of the primary server's Oracle Home directory by creating a UNIX link and referencing that instead when creating the RMAN backups for the standby, as shown below. RMAN expects to back up and restore from the same ORACLE_HOME directory, but PrimaryServer's Oracle Home is different than StandbyServer's Oracle Home in this case. So, it's time to pull a UNIX trick out of the bag!
Make an RMAN backup of PROD to "/oratest10/ora102/dbs"
(the Oracle Home on StandbyServer) on PrimaryServer to match the $ORACLE_HOME on
StandbyServer (see "env ORACLE_HOME" on StandbyServer) by creating the
/oratest10/ora102/dbs link on PrimaryServer to point to $ORACLE_HOME/dbs on the
primary server:
login root
mkdir -p /oratest10/ora102
ln -s /pgms/oracle/product/v10203/dbs /oratest10/ora102/dbs
chown oracle.dba /oratest10/ora102
chmod 755 /oratest10/ora102
Create a full RMAN backup of PROD to "/oratest10/ora102/dbs"
(which means we can't use my rmanclone.shl script - we'll have to do RMAN
manually), along with the standby control file, making sure the logs on the
primary are all archived (change the date and time to match yours). These will
have to be FTP'ed to the Oracle Home on StandbyServer.
login oracle
PROD
export NLS_DATE_FORMAT='DD-MON-YY HH24:MI:SS'
export bkup_date=`date +"%y%m%d%H%M%S%aFULL`
export bkup_tag="${ORACLE_SID}_${bkup_date}"
echo $bkup_tag
date
rman target / <<EOF
configure channel 1 device type disk
format '/oratest10/ora102/dbs/%U';
configure channel 2 device type disk
format '/oratest10/ora102/dbs/%U';
backup incremental level=0 database
tag='${bkup_tag}_dbf';
sql 'alter system archive log
current';
backup archivelog all tag='${bkup_tag}_arc';
backup spfile tag='${bkup_tag}_spf';
backup current controlfile tag='${bkup_tag}_ctl';
backup current controlfile for
standby tag='${bkup_tag}_sctl';
sql 'alter system archive log
current';
backup archivelog all not backed up 1
times tag='${bkup_tag}_sarc';
list backup of controlfile completed
after "to_date('05-MAY-09 12:00:00','DD-MON-YY HH24:MI:SS')";
list backup summary completed after "to_date('05-MAY-09
12:00:00','DD-MON-YY HH24:MI:SS')";
configure channel 1 device type disk
clear;
configure channel 2 device type disk
clear;
exit
EOF
Recreating a Data Guard Standby Database Using RMAN
NOTE: Use my rmanbackup.shl script dated 6/30/09 or later for this. It includes creating a standby controlfile during the backups. If your version does not include a 6/30/09 revision, get the latest version of the rmanbackup.shl script.
Rereating a Data Guard standby database on StandbyServer for the primary PROD database on PrimaryServer using RMAN is similar to creating a Data Guard standby database using RMAN, but leaving out some of the steps that had already been done when initially creating the standby. We do not need to add the tnsnames.ora entries or the oratab entry because they already exist, and we will use the same spfile and password file for the standby database that currently exists. Below are my notes on how I did this for our production database. (The standby had gotten out of sync when one of the archive logs on the primary was deleted, and the standby stopped applying any changes later than that missing archive log file.)
THESE STEPS ARE DONE ON PrimaryServer:
Create a full backup of PROD, which will have to be FTP'ed
to StandbyServer (the backup includes the standby control file):
login oracle
PROD
rmanbackup.shl PROD full
Get the list of backup files from today to FTP to
StandbyServer:
find $ORACLE_HOME/dbs \( -name '*_1_1' -o -name '*_1_1_dbf'
-o -name '*_1_1_spf' -o -name '*_1_1_ctl' -o -name '*_1_1_arc' -o -name
'*_1_1_sby' \) |
sed 's/^/ls -ltr /' | sh | grep ' Jun
30 08:2' | grep PROD | sed 's/.\{58\}/get /'
shows:
get /pgms/oracle/product/v10203/dbs/PROD_n9kis3tp_1_1_sby
get /pgms/oracle/product/v10203/dbs/PROD_nbkis3tr_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_nakis3tr_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_nckis482_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_ndkis482_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nekis48i_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nfkis48i_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_ngkis492_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nhkis492_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nikis49h_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_njkis49h_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nkkis4a1_1_1_arc
get
/pgms/oracle/product/v10203/dbs/PROD_nlkis4a1_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nmkis4ag_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nnkis4ah_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nokis4b0_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_npkis4b1_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nqkis4bg_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nrkis4bg_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nskis4c1_1_1_spf
get /pgms/oracle/product/v10203/dbs/PROD_ntkis4c3_1_1_ctl
Generate the commands to remove and create the directories
for the standby database (the remove commands are used in the case where a
standby database had been created before on StandbyServer):
sqlplus "/ as sysdba"
set heading off feedback off
spool makedirs.shl
select distinct ' rm -r ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_data_files
union
select distinct ' rm -r ' ||
substr(substr(value,instr(value,'LOCATION=')+9),1,
instr(substr(value,instr(value,'LOCATION=')+9),' ')-13)
from
v$parameter where name between 'log_archive_dest_1' and
'log_archive_dest_10' and instr(value,'LOCATION=') > 0
union
select distinct ' rm -r ' ||
substr(value,1,instr(value,'/',-1)-1) from v$parameter
where name in
('background_dump_dest','user_dump_dest','core_dump_dest',
'audit_file_dest','log_archive_dest')
and value is
not null
union
select distinct 'mkdir -p ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_data_files
union
select distinct 'mkdir -p ' ||
substr(file_name,1,instr(file_name,'/',-1)-1)
from
dba_temp_files
union
select distinct 'mkdir -p ' || value
from v$parameter
where name in
('background_dump_dest','user_dump_dest','core_dump_dest',
'audit_file_dest','log_archive_dest')
and value is
not null
union
select distinct 'mkdir -p ' ||
substr(substr(value,instr(value,'LOCATION=')+9),1,
instr(substr(value,instr(value,'LOCATION=')+9),' ')-1)
from
v$parameter where name between 'log_archive_dest_1' and
'log_archive_dest_10' and instr(value,'LOCATION=') > 0;
spool off
exit
vi /home/oracle/makedirs.shl
:1,/^ rm /-1d
:$d
:wq
cat makedirs.shl
shows (along with the SQL above,
which can be deleted from makedirs.shl):
rm -r /data/oradata/PROD
rm -r /ndxs/oradata/PROD
rm -r /orcl/oradata/PROD
rm -r /pgms/oradata/PROD
mkdir -p
/data/oradata/PROD
mkdir -p /ndxs/oradata/PROD
mkdir -p /orcl/oradata/PROD/archivelogs
mkdir -p /pgms/oradata/PROD/audit
mkdir -p /pgms/oradata/PROD/bdump
mkdir -p /pgms/oradata/PROD/cdump
mkdir -p /pgms/oradata/PROD/udump
Generate the SQL to create the standby redo log groups for
the new StandbyServer standby database:
sqlplus "/ as sysdba"
column o1 noprint
column o2 noprint
column maxgroup new_value maxgroup
select max(group#) maxgroup from
v$logfile where type = 'ONLINE';
select group# o1,1 o2,'alter database
add standby logfile group ' ||
to_char(group#+&maxgroup)
|| ' ('
from v$log
union all
select group#,2,' ''' ||
replace(replace(member,group#,group#+&maxgroup),
'/log_','/stby_log_')
|| ''','
from
v$logfile lf1 where member not in (select max(member) from v$logfile lf2
where
lf1.group# = lf2.group#) and type = 'ONLINE'
union all
select l1.group#,3,' ''' ||
replace(replace(member,l1.group#,l1.group#+&maxgroup),
'/log_','/stby_log_')
|| ''') size ' || bytes / 1024 || 'K;'
from
v$logfile lf1,v$log l1 where lf1.group# = l1.group#
and member =
(select max(member) from v$logfile lf2 where lf1.group# = lf2.group#)
and type =
'ONLINE'
union all
select group#+1,1,'alter database add
standby logfile group ' ||
to_char(group#+1+&maxgroup)
|| ' (' from v$log
where group#
= &maxgroup
union all
select group#+1,2,' ''' ||
replace(replace(member,group#,group#+1+&maxgroup),
'/log_','/stby_log_')
|| ''',' from v$logfile lf1 where group# = &maxgroup
and member
not in (select max(member) from v$logfile lf2 where lf1.group# = lf2.group#)
and type =
'ONLINE'
union all
select
l1.group#+1,3,' ''' || replace(replace(member,l1.group#,l1.group#+1+&maxgroup),
'/log_','/stby_log_')
|| ''') size ' || bytes / 1024 || 'K;'
from
v$logfile lf1,v$log l1 where lf1.group# = l1.group#
and l1.group#
= &maxgroup
and member =
(select max(member) from v$logfile lf2 where lf1.group# = lf2.group#)
and type =
'ONLINE'
order by
1,2,3;
exit
shows:
alter database add standby logfile group 4 (
'/orcl/oradata/PROD/stby_log_PROD_4A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_4B.rdo') size 4096K;
alter database add standby logfile group 5 (
'/orcl/oradata/PROD/stby_log_PROD_5A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_5B.rdo') size 4096K;
alter database add standby logfile group 6 (
'/orcl/oradata/PROD/stby_log_PROD_6A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_6B.rdo') size 4096K;
alter database add standby logfile group 7 (
'/orcl/oradata/PROD/stby_log_PROD_7A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_7B.rdo') size 4096K;
THESE STEPS ARE DONE ON StandbyServer:
Log into the unix oracle account, set the ORACLE_SID to
the standby SID, and shut down the current standby database:
login oracle
PROD
sqlplus "/ as sysdba"
shutdown immediate
exit
FTP the backup files and the standby control file from
PrimaryServer to StandbyServer:
cd $ORACLE_HOME/dbs
ftp PrimaryServer.uaex.edu
oracle
type ascii
get
/home/oracle/makedirs.shl
type binary
get /pgms/oracle/product/v10203/dbs/PROD_n9kis3tp_1_1_sby
get /pgms/oracle/product/v10203/dbs/PROD_nbkis3tr_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_nakis3tr_1_1_dbf
get /pgms/oracle/product/v10203/dbs/PROD_nckis482_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_ndkis482_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nekis48i_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nfkis48i_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_ngkis492_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nhkis492_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nikis49h_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_njkis49h_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nkkis4a1_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nlkis4a1_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nmkis4ag_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nnkis4ah_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nokis4b0_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_npkis4b1_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nqkis4bg_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nrkis4bg_1_1_arc
get /pgms/oracle/product/v10203/dbs/PROD_nskis4c1_1_1_spf
get /pgms/oracle/product/v10203/dbs/PROD_ntkis4c3_1_1_ctl
bye
Delete and recreate the directories for the new PROD
database on StandbyServer. Also, save off and restore the remove_old_logs.shl
and fillup.shl scripts if they exist in the archivelogs directory (these are
some local scripts that I use - you may have other scripts in your archivelogs
directory that you want to preserve a copy of):
cd
cp -p /orcl/oradata/${ORACLE_SID}/archivelogs/remove_old_logs.shl
/home/oracle/remove_old_logs.${ORACLE_SID}.shl
cp -p /orcl/oradata/${ORACLE_SID}/archivelogs/fillup.shl
/home/oracle/fillup.${ORACLE_SID}.shl
sh /home/oracle/makedirs.shl
cp -p /home/oracle/remove_old_logs.${ORACLE_SID}.shl
/orcl/oradata/${ORACLE_SID}/archivelogs/remove_old_logs.shl
cp -p /home/oracle/fillup.${ORACLE_SID}.shl /orcl/oradata/${ORACLE_SID}/archivelogs/fillup.shl
Create the new PROD standby database on StandbyServer from
the PROD RMAN backups from PrimaryServer:
sqlplus "/ as sysdba"
startup nomount
exit
rman target sys/<sys password>@PrimaryServer_prod auxiliary /
duplicate target database for standby
nofilenamecheck;
exit
Start up managed recovery for the new PROD standby
database on StandbyServer:
sqlplus "/ as sysdba"
alter database recover managed
standby database disconnect from session;
Note: This
creates the redo log files in /orcl/oradata/PROD.
exit
Do a log switch on the PROD primary database (you may have
to do the switch several times), and check to see that the archive logs are
coming across to the standby server:
PrimaryServer:
sqlplus "/ as sysdba"
alter system archive log current;
exit
StandbyServer:
ls -ltr /orcl/oradata/PROD/archivelogs
Add the standby log files for the new PROD standby
database on StandbyServer and start up managed recovery (note: this can't be
done until archiving has been started to the new standby from the primary by
doing a log switch):
sqlplus "/ as sysdba"
alter database recover managed
standby database cancel;
alter database open read only;
column member format a55
select vs.group#,vs.bytes,vl.member
from v$standby_log vs,v$logfile vl
where
vs.group# = vl.group# order by vs.group#,vl.member;
alter database add standby logfile
group 4 (
'/orcl/oradata/PROD/stby_log_PROD_4A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_4B.rdo')
size 4096K;
alter database add standby logfile
group 5 (
'/orcl/oradata/PROD/stby_log_PROD_5A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_5B.rdo')
size 4096K;
alter database add standby logfile
group 6 (
'/orcl/oradata/PROD/stby_log_PROD_6A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_6B.rdo')
size 4096K;
alter database add standby logfile
group 7 (
'/orcl/oradata/PROD/stby_log_PROD_7A.rdo',
'/orcl/oradata/PROD/stby_log_PROD_7B.rdo')
size 4096K;
select vs.group#,vs.bytes,vl.member
from v$standby_log vs,v$logfile vl
where
vs.group# = vl.group# order by vs.group#,vl.member;
alter database recover managed
standby database disconnect from session;
exit
Creating a Local Data Guard Standby Database on Windows (added 5/30/10)
Below is how I created a local Data Guard standby database (ORC2) for a primary database (ORCL) on Windows. It also uses RMAN to back up and duplicate the database.
Create a pfile from the primary, if you don't have one already:
Make
Data Guard additions/changes, resulting in the following in the
initORCL.ora file (also changing the dump_dest directories for ORCL;
note: the dump_dest parameters have been depreciated in Oracle 11g):
Copy and edit the standby's pfile to change the SID and to add the Data Guard parameters, such as:
Add the standby database to the tnsnames file, if it is not already there:
Add the standby database to the listener.ora file, if it is not already there:
Create a Windows service for the standby:
Create the standby's data file, temp file, dump file, and archivelog directory(s) if they don't exist:
Also make the dump file directories declared in the init.ora files (but, these have been depreciated in Oracle 11g):
Delete the standby's datafiles, control files, and spfile if they currently exist:
Or, could use RMAN to drop the database:
Delete the standby's spfile if the above didn't catch it:
Copy the password file from the primary (PWDorcl.ora) to the standby (PWDorc2.ora):
Create the standby's spfile from the edited pfile and start up the standby in the nomount state:
Get
the date and time (substitute in the tag parameters below) and createan
RMAN backup of the primary including the standby's control file:
Generate the SQL to create the standby redo log groups for the new standby database:
Add
the parameters for the Data Guard settings to the primary database's
spfile.ora file (could have done this without shutting down the
database by doing "alter system set" commands):
Run the RMAN duplicate command to copy the primary to the standby as of a given date and time:
Start up managed recovery for the new standby database:
Do
a log switch on the primary (you may have to do the switch several
times), and check to see that the archive logs are coming across to the
standby server:
Add
the standby log files for the new standby and restart managed recovery
(note: this can't be done until archiving has been started to the new
standby from the primary by doing a log switch):
You Are Visitor Number |
This Page Was Last Updated on 05/30/10 |
Copyright © 2009 by Maristream.
All information, scripts, forms, and other material
on this web site are freely available to all Banner and Oracle Database Administrators,
Systems Administrators, Programmers, and others that may need it.
The webmaster who maintains this web site may be reached at srea@maristream.org. Visit our other web sites:
|
Maristream - New Product Research and Development |
Disclaimer: As with all software, especially where it affects your vital data, make sure that you examine theses scripts and that you understand what they do before you use them to see if they would have any adverse effect on your particular setup or database layout. Make a full backup of your database in case you have to revert to your original copy of the database before the scripts were run. Use these scripts at your own risk. As a condition of using these scripts, you agree to hold harmless both Maristream and Stephen Rea for any problems that they may cause or other situations that may arise from their use, and that neither Maristream nor I will be held liable for those consequences.