Create a Clone DB from Backup on the Same Server (or remote) Mustafa, 2021-04-262021-04-27 Hi, I wanted to create a post series about cloning/duplicating database on the same or remote servers. There are so many options and combinations about this like rman duplicate database with/without target/source db connection, rman restore using backups, ASM to OS or OS to ASM, same server or remote server, OMF or regular file naming etc… What I am about to demonstrate is creating a TEST db from PROD db on the same server with “no ASM” only OS file system using PROD DB backups (not rman duplicate database command). of course, you can use same method to create a TEST db on “remote server” just by copying backups and archivelogs (maybe a copy of controlfile too) to same location on a remote server. So, Lets get started: source database (let’s say this is your PROD db which is source db) SID : orcl duplicate/target database (let’s say this is the TEST db which you want to create ) SID : dup method : using backups only (no duplicate database command) server : same or remote (you can copy your backups to a remote server under same location with prod server and follow the same steps) file naming : OMF (Oracle Managed Files) OS : Linux / Windows (Windows steps are also very similar. I will add some notes for windows). Database version: 19c (19.3) while doing this, I will try to explain why we do that step and important files of database. 1- Parameter File Parameter file is the first file to read while starting a database instance. it defines vital and mandatory parameters to create an instance, like database name. So, to create a new database, first we need parameter file. it could be either SPFILE (binary version) or PFILE (text version). Since we can not create a binary file easily, I will create text parameter file and then create binary version of it. there thousands of parameters in Oracle but just 3 of them is enough to create an instance. under ORACLE_HOME/dbs directory, create an empty file with name initdup.ora and put those into it: Oracle PL/SQL db_name=orcl db_unique_name=dup db_create_file_dest=/u01/app/oracle/oradata 123 db_name=orcldb_unique_name=dupdb_create_file_dest=/u01/app/oracle/oradata Windows OS Note: for Windows OS, directory is ORACLE_HOME/database and file name is INITDUP.ora by default. Also you need to create a Windows Service for Oracle Database instance using “oradim” tool first: “oradim -NEW -SID dup -STARTMODE auto” is enough to achieve this. what are these 3 parameters? db_name: name of the database which is “orcl” for now. wait what? don’t we create a new db called “dup” why is this orcl ? because we will use orcl database backups to create our database and I don’t want to show all backup files to rman. so We will act as if we are creating an db called “orcl” but we will change it while doing this. we will use orcl is just for finding backups and restore/recover datafiles. db_unique_name: this parameter is set to null by default and if it is null, it’s value is db_name. so you can think it as if Oracle uses it “NVL(db_unique_name, db_name)”. as you see this parameter is set to “dup” which is name of new database. while doing restore/recover operations, if rman does not know that this is a different database then it will restore /recover source database (orcl). with this parameter we are identifying our unique database. db_create_file_dest: this is the parameter that makes your database as OMF (oracle managed files) which means you don’t need to give any file name. just say “add a datafile to this tablespace”; Oracle will add new datafile and give a name to it. we don’t need to know what is the name of a datafile. this parameter also, of course, tells that where the files will be created. by saying files not just datafiles. also redo logs and control files too. this is the “main directory” for a database. so path pattern is like this: /u01/app/oracle/oradata/<instance_name>/datafile => for datafiles /u01/app/oracle/oradata/<instance_name>/controlfile => for controlfiles /u01/app/oracle/oradata/<instance_name>/onlinelog => for redo logs. in our example, instance name will be “dup”. Now, we have a parameter file so we can start our database instance. Do not forget that our source database is also on the same server so we must be careful not to mess with source db. So, I will set ORACLE_SID environment variable first: Oracle PL/SQL oracle@Linux7 dbs $ export ORACLE_SID=dup oracle@Linux7 dbs $ sqlplus / as sysdba SQL*Plus: Release 19.0.0.0.0 - Production on Mon Apr 26 17:23:10 2021 Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. Connected to an idle instance. SQL> create spfile from pfile; File created. SQL> startup nomount; ORACLE instance started. Total System Global Area 306183456 bytes Fixed Size 8895776 bytes Variable Size 239075328 bytes Database Buffers 50331648 bytes Redo Buffers 7880704 bytes SQL> 1234567891011121314151617181920212223 oracle@Linux7 dbs $ export ORACLE_SID=duporacle@Linux7 dbs $ sqlplus / as sysdba SQL*Plus: Release 19.0.0.0.0 - Production on Mon Apr 26 17:23:10 2021Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle. All rights reserved. Connected to an idle instance. SQL> create spfile from pfile; File created. SQL> startup nomount;ORACLE instance started. Total System Global Area 306183456 bytesFixed Size 8895776 bytesVariable Size 239075328 bytesDatabase Buffers 50331648 bytesRedo Buffers 7880704 bytesSQL> Windows OS Note: in Windows you can set your environment variable ORALCE_HOME by using “set” command not export. “set ORACLE_SID=dup”. as you can see we started an instance already. of course we don’t even have a datafile yet but still this is an instance. we didn’t specify any memory parameter for example in pfile but they have all default values so it will work but of course if you have a defined configuration you can add them into pfile (initdup.ora) so db instance will be using them. I created SPFILE before starting the instance so spfiledup.ora is created under ORACLE_HOME/dbs (ORACLE_HOME/database for windows os ) directory and instance is started by this spfile. so we have a basic parameter file and our instance is up. let’s continue with step 2. 2- Control File control file is the next step while starting a database. it stores very critical information like where are datafiles, backups, redo logs. Also many database limits are defined in controlfile like maximum number of data files which can be created in db (MAXDATAFFILES). to restore control file, first I will backup as copy control file from source db (which is orcl, our prod database). so, from “orcl”, first we create control file copy. Oracle PL/SQL export ORACLE_SID=orcl rman target / backup as copy current controlfile format '/tmp/controlORCL.ora'; 12345 export ORACLE_SID=orcl rman target / backup as copy current controlfile format '/tmp/controlORCL.ora'; so I created controlORCL.ora file under /tmp which is copy of current control file of orcl db. now let’s turn to dup db and restore it. Oracle PL/SQL export ORACLE_SID=dup rman target / Recovery Manager: Release 19.0.0.0.0 - Production on Mon Apr 26 17:55:17 2021 Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved. connected to target database (not started) RMAN> restore controlfile from '/tmp/controlORCL.ora'; Starting restore at 2021-04-26 18:06:02 using channel ORA_DISK_1 channel ORA_DISK_1: copied control file copy output file name=/u01/app/oracle/oradata/DUP/controlfile/o1_mf_j8foptb7_.ctl Finished restore at 2021-04-26 18:06:03 12345678910111213141516171819 export ORACLE_SID=dup rman target / Recovery Manager: Release 19.0.0.0.0 - Production on Mon Apr 26 17:55:17 2021Version 19.3.0.0.0 Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved. connected to target database (not started) RMAN> restore controlfile from '/tmp/controlORCL.ora'; Starting restore at 2021-04-26 18:06:02using channel ORA_DISK_1 channel ORA_DISK_1: copied control file copyoutput file name=/u01/app/oracle/oradata/DUP/controlfile/o1_mf_j8foptb7_.ctlFinished restore at 2021-04-26 18:06:03 command is “restore controlfile from ‘/tmp/controlORCL.ora’;” and control file restored under: /u01/app/oracle/oradata/DUP/controlfile/ directory. as you see it is under DUP directory because of db_unique_name parameter. We restored our control file but this is not entirely correct because this control file is belong to orcl db and it knows this database as “orcl” but we will deal with that later. Now, this control file knows where backups are, so we can restore datafiles but first we must take our database to mount mode. Oracle PL/SQL RMAN> alter database mount; 1 RMAN> alter database mount; Now, restore database BUT as I mentioned, this control file belongs to “orcl” db so if I run “restore database” it will restore datafiles to original “orcl” db datafile locations. You must be careful here, you don’t want to shutdown your source db. to restore those datafiles to a different location (dup db datafile location) we will use “set newname” command: Oracle PL/SQL RMAN> run { set newname for database to new; restore database; } executing command: SET NEWNAME Starting restore at 2021-04-26 21:21:09 allocated channel: ORA_DISK_1 channel ORA_DISK_1: SID=7 device type=DISK channel ORA_DISK_1: starting datafile backup set restore channel ORA_DISK_1: specifying datafile(s) to restore from backup set channel ORA_DISK_1: restoring datafile 00001 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_system_%u_.dbf channel ORA_DISK_1: restoring datafile 00003 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_sysaux_%u_.dbf channel ORA_DISK_1: restoring datafile 00004 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_undotbs1_%u_.dbf channel ORA_DISK_1: restoring datafile 00007 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_users_%u_.dbf channel ORA_DISK_1: reading from backup piece /u01/app/oracle/fast_recovery_area/ORCL/backupset/2021_04_26/o1_mf_nnndf_TAG20210426T163636_j8fjh46t_.bkp channel ORA_DISK_1: piece handle=/u01/app/oracle/fast_recovery_area/ORCL/backupset/2021_04_26/o1_mf_nnndf_TAG20210426T163636_j8fjh46t_.bkp tag=TAG20210426T163636 channel ORA_DISK_1: restored backup piece 1 channel ORA_DISK_1: restore complete, elapsed time: 00:00:07 Finished restore at 2021-04-26 21:21:17 12345678910111213141516171819202122 RMAN> run { set newname for database to new; restore database; } executing command: SET NEWNAME Starting restore at 2021-04-26 21:21:09allocated channel: ORA_DISK_1channel ORA_DISK_1: SID=7 device type=DISK channel ORA_DISK_1: starting datafile backup set restorechannel ORA_DISK_1: specifying datafile(s) to restore from backup setchannel ORA_DISK_1: restoring datafile 00001 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_system_%u_.dbfchannel ORA_DISK_1: restoring datafile 00003 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_sysaux_%u_.dbfchannel ORA_DISK_1: restoring datafile 00004 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_undotbs1_%u_.dbfchannel ORA_DISK_1: restoring datafile 00007 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_users_%u_.dbfchannel ORA_DISK_1: reading from backup piece /u01/app/oracle/fast_recovery_area/ORCL/backupset/2021_04_26/o1_mf_nnndf_TAG20210426T163636_j8fjh46t_.bkpchannel ORA_DISK_1: piece handle=/u01/app/oracle/fast_recovery_area/ORCL/backupset/2021_04_26/o1_mf_nnndf_TAG20210426T163636_j8fjh46t_.bkp tag=TAG20210426T163636channel ORA_DISK_1: restored backup piece 1channel ORA_DISK_1: restore complete, elapsed time: 00:00:07Finished restore at 2021-04-26 21:21:17 since I use OMF, ” set newname for database to new;” means, restore datafiles to wherever db_file_create_dest parameter points. by default, control file knows where those datafiles are so if I restore them, it will be under ORCL db location. “set newname for database to new” cause re-read parameter file and datafile location information and restore datafiles to there. as you see in the output, datafiles are restore under DUP location (ex: channel ORA_DISK_1: restoring datafile 00001 to /u01/app/oracle/oradata/DUP/datafile/o1_mf_system_%u_.dbf) . perfect. now we have datafiles too but we can not open database right away. first, even if we are able to open database, control file is still old and will look for datafiles under ORCL directory not DUP directory. we must tell controlfile to use those recently restored datafiles as primary datafiles. so we must “switch database to copy”. Oracle PL/SQL RMAN> switch database to copy; datafile 1 switched to datafile copy "/u01/app/oracle/oradata/DUP/datafile/o1_mf_system_j8g14p2t_.dbf" datafile 3 switched to datafile copy "/u01/app/oracle/oradata/DUP/datafile/o1_mf_sysaux_j8g14p2w_.dbf" datafile 4 switched to datafile copy "/u01/app/oracle/oradata/DUP/datafile/o1_mf_undotbs1_j8g14p2y_.dbf" datafile 7 switched to datafile copy "/u01/app/oracle/oradata/DUP/datafile/o1_mf_users_j8g14p2z_.dbf" 123456 RMAN> switch database to copy; datafile 1 switched to datafile copy "/u01/app/oracle/oradata/DUP/datafile/o1_mf_system_j8g14p2t_.dbf"datafile 3 switched to datafile copy "/u01/app/oracle/oradata/DUP/datafile/o1_mf_sysaux_j8g14p2w_.dbf"datafile 4 switched to datafile copy "/u01/app/oracle/oradata/DUP/datafile/o1_mf_undotbs1_j8g14p2y_.dbf"datafile 7 switched to datafile copy "/u01/app/oracle/oradata/DUP/datafile/o1_mf_users_j8g14p2z_.dbf" let’s recover database now: Oracle PL/SQL RMAN> recover database; Starting recover at 2021-04-26 21:29:08 using channel ORA_DISK_1 starting media recovery archived log for thread 1 with sequence 16 is already on disk as file /u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_1_j6xpd2b0_.log archived log file name=/u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_1_j6xpd2b0_.log thread=1 sequence=16 media recovery complete, elapsed time: 00:00:02 Finished recover at 2021-04-26 21:29:10 1234567891011 RMAN> recover database; Starting recover at 2021-04-26 21:29:08using channel ORA_DISK_1 starting media recovery archived log for thread 1 with sequence 16 is already on disk as file /u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_1_j6xpd2b0_.logarchived log file name=/u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_1_j6xpd2b0_.log thread=1 sequence=16media recovery complete, elapsed time: 00:00:02Finished recover at 2021-04-26 21:29:10 this will apply all changes which are made after the backup. it will read archivelog files and apply them into datafiles. Good!, can we open database now? well, no 🙂 why? because as I said earlier, this controlfile is still a stranger! it knows this database as “orcl” but it is not anymore! Since we get everything we want (controlfile, datafiles, recover operation) now we can change our controlfile. to achieve that we must re-create control file and tell “this is dup db anymore”. of course before do that, we must change “db_name” parameter anymore. it is still “orcl”. we can set it as “dup” now but this parameter can not be changed without restart. Problem about that, you can not change db_name with “alter system” if you are using spfile. so stesp are these: I create pfile shutdown database modify pfile and change db_name parameter to “dup”, remove db_unique_name parameter create spfile again. ===> This is very important. if you forgot this step, when you start db, it will be using old values. start db in mount mode. create controlfile create script using “alter database backup controlfile to trace” command. Oracle PL/SQL RMAN> exit; ---------------------- sqlplus / as sysdba SQL> create pfile from spfile; File created. SQL> shutdown immediate; ORA-01109: database not open Database dismounted. ORACLE instance shut down. SQL> exit; vim $ORACLE_HOME/dbs/initdup.ora --- change db_name to dup and REMOVE db_unique_name. sqlplus / as sysdba SQL> create spfile from pfile; SQL> startup mount SQL> alter database backup controlfile to trace as '/tmp/control_file.txt'; Database altered. 123456789101112131415161718192021222324252627282930 RMAN> exit; ---------------------- sqlplus / as sysdbaSQL> create pfile from spfile; File created. SQL> shutdown immediate;ORA-01109: database not open Database dismounted.ORACLE instance shut down.SQL> exit; vim $ORACLE_HOME/dbs/initdup.ora --- change db_name to dup and REMOVE db_unique_name. sqlplus / as sysdba SQL> create spfile from pfile; SQL> startup mount SQL> alter database backup controlfile to trace as '/tmp/control_file.txt'; Database altered. finally we need to re create our controlfile to make it completely a dup db controlfile. I created controlfile script under the tmp directory. you can open it any text editor. you will find 2 “create controlfile ” command. one with NORESETLOGS and the other RESETLOGS. on a new database, to create redo logs, we must use RESETLOGS clause. so I will just write here RESETLOGS version in control_file.txt file. Oracle PL/SQL CREATE CONTROLFILE REUSE DATABASE "ORCL" RESETLOGS ARCHIVELOG MAXLOGFILES 16 MAXLOGMEMBERS 3 MAXDATAFILES 100 MAXINSTANCES 8 MAXLOGHISTORY 292 LOGFILE GROUP 1 ( '/u01/app/oracle/oradata/ORCL/onlinelog/o1_mf_1_j6xpd19n_.log', '/u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_1_j6xpd2b0_.log' ) SIZE 200M BLOCKSIZE 512, GROUP 2 ( '/u01/app/oracle/oradata/ORCL/onlinelog/o1_mf_2_j6xpd1bk_.log', '/u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_2_j6xpd291_.log' ) SIZE 200M BLOCKSIZE 512, GROUP 3 ( '/u01/app/oracle/oradata/ORCL/onlinelog/o1_mf_3_j6xpd1c4_.log', '/u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_3_j6xpd28w_.log' ) SIZE 200M BLOCKSIZE 512 -- STANDBY LOGFILE DATAFILE '/u01/app/oracle/oradata/DUP/datafile/o1_mf_system_j8g14p2t_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_sysaux_j8g14p2w_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_undotbs1_j8g14p2y_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_users_j8g14p2z_.dbf' CHARACTER SET AL32UTF8 ; 123456789101112131415161718192021222324252627 CREATE CONTROLFILE REUSE DATABASE "ORCL" RESETLOGS ARCHIVELOG MAXLOGFILES 16 MAXLOGMEMBERS 3 MAXDATAFILES 100 MAXINSTANCES 8 MAXLOGHISTORY 292LOGFILE GROUP 1 ( '/u01/app/oracle/oradata/ORCL/onlinelog/o1_mf_1_j6xpd19n_.log', '/u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_1_j6xpd2b0_.log' ) SIZE 200M BLOCKSIZE 512, GROUP 2 ( '/u01/app/oracle/oradata/ORCL/onlinelog/o1_mf_2_j6xpd1bk_.log', '/u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_2_j6xpd291_.log' ) SIZE 200M BLOCKSIZE 512, GROUP 3 ( '/u01/app/oracle/oradata/ORCL/onlinelog/o1_mf_3_j6xpd1c4_.log', '/u01/app/oracle/fast_recovery_area/ORCL/onlinelog/o1_mf_3_j6xpd28w_.log' ) SIZE 200M BLOCKSIZE 512-- STANDBY LOGFILEDATAFILE '/u01/app/oracle/oradata/DUP/datafile/o1_mf_system_j8g14p2t_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_sysaux_j8g14p2w_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_undotbs1_j8g14p2y_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_users_j8g14p2z_.dbf'CHARACTER SET AL32UTF8; as you can see, controlfile thinks that this is ORCL database and all redo logs are also under ORCL directory (‘/u01/app/oracle/oradata/ORCL/onlinelog/o1_mf_1_j6xpd19n_.log’,). This is also an important step. if you don’t change those ORCLs to DUP, you might cause damage to your source database which is orcl in my example. Since I use OMF, and I always use OMF just for these reasons, all I need to do is remove those path. Also, since we want to change database name, we must add SET clause after “create controlfile reuse” part. Please note that, just changing ORCLs to DUP in this script won’t work because datafiles also has database name information in their header file. so we must use SET which means, “set database name”. this will also update datafile headers. to create controlfile again, you must be in nomount mode (in mount mode, cotnrolfiles are already in use, you can not change them.) Oracle PL/SQL SQL> shu immediate; SQL> startup nomount; SQL> CREATE CONTROLFILE REUSE SET DATABASE "DUP" RESETLOGS ARCHIVELOG MAXLOGFILES 16 MAXLOGMEMBERS 3 MAXDATAFILES 100 MAXINSTANCES 8 MAXLOGHISTORY 292 LOGFILE GROUP 1 SIZE 200M BLOCKSIZE 512, GROUP 2 SIZE 200M BLOCKSIZE 512, GROUP 3 SIZE 200M BLOCKSIZE 512 -- STANDBY LOGFILE DATAFILE '/u01/app/oracle/oradata/DUP/datafile/o1_mf_system_j8g14p2t_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_sysaux_j8g14p2w_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_undotbs1_j8g14p2y_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_users_j8g14p2z_.dbf' CHARACTER SET AL32UTF8 ; Control file created. 123456789101112131415161718192021222324 SQL> shu immediate; SQL> startup nomount; SQL> CREATE CONTROLFILE REUSE SET DATABASE "DUP" RESETLOGS ARCHIVELOG MAXLOGFILES 16 MAXLOGMEMBERS 3 MAXDATAFILES 100 MAXINSTANCES 8 MAXLOGHISTORY 292LOGFILE GROUP 1 SIZE 200M BLOCKSIZE 512, GROUP 2 SIZE 200M BLOCKSIZE 512, GROUP 3 SIZE 200M BLOCKSIZE 512-- STANDBY LOGFILEDATAFILE '/u01/app/oracle/oradata/DUP/datafile/o1_mf_system_j8g14p2t_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_sysaux_j8g14p2w_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_undotbs1_j8g14p2y_.dbf', '/u01/app/oracle/oradata/DUP/datafile/o1_mf_users_j8g14p2z_.dbf'CHARACTER SET AL32UTF8; Control file created. finally, we have a real controlfile for dup db. after now, we can open it with resetlogs option. creating controlfile will also take our database into “mount” mode so no need another “alter database mount” command. Oracle PL/SQL SQL> alter database open resetlogs; Database altered. SQL> select name from v$database; NAME --------- DUP SQL> select instance_name from v$instance; INSTANCE_NAME ---------------- dup 123456789101112131415 SQL> alter database open resetlogs; Database altered. SQL> select name from v$database; NAME---------DUP SQL> select instance_name from v$instance; INSTANCE_NAME----------------dup viola! we have a new db with a new name which is also created from another database backup. you can use this on the same or remote servers. as said before, only difference is copying backups to remote server. I hope this helps. I will try to write for other methods too like duplicate database etc. please make a comment, so I can believe that not daily 30 visitors on my blog are bots 🙂 wish you healthy days. Important Edit: you might ask why we don’t create controlfile before all those operations. it has 2 reasons. creating control file will cause loosing the location of backups and more importantly, create controlfile command validates the datafiles if they are in the correct locations. so we can not create controlfile without having datafiles. 12c 18c 19c 21c Administration clone databasecreate database with new namecreate test databaseduplicate dbnew db from backupsstep by step create new db
nice write up, thanks much, I was struggling trying to simulate a clone to a new server, but using the same server in my test environment, the redo of the clone kept messing things up. This method is much cleaner, much thx again Reply
Hi Ken, thanks for your kind comment. I wanted to show actual steps while cloning a database. RMAN “duplicate database” command kind of run those commands. You can always use duplicate database which has less effort. by the way, I realized that I didn’t mention about directory objects in database. you should always check dba_directories and recreate them if necessary. for example “data_pump_dir” directory contains database name so after cloning you must recreate directory with new database name. Reply