8i | 9i | 10g | 11g | 12c | 13c | 18c | 19c | 21c | 23c | Misc | PL/SQL | SQL | RAC | WebLogic | Linux

Home » Articles » 11g » Here

Direct NFS (DNFS) CloneDB in Oracle Database 11g Release 2 (Patchset 11.2.0.2 onward)

CloneDB is a new Direct NFS (DNFS) feature introduced in the 11.2.0.2 database patchset. Rather than using the traditional RMAN database duplication, CloneDB uses dNFS technology to instantly fire up a clone using an existing backup of a database as the data store. The clone uses copy-on-write technology, so only changed blocks need to be stored locally, while the unchanged data is referenced directly from the backup files. This drastically increases the speed of cloning a system and means that several separate clones can function against a single set of backup datafiles, thus saving considerable amounts of space.

The backups used as the read-only source datafiles must not change during the lifespan of the instance. They can't be wound forward, like incrementally updated image copy backups, without discarding the clonedb clones.

For this test we have the following servers.

NFS Server:
  Name       : nas1
  IP Address : 192.168.2.2
  NFS share  : /u01/nfs_shares/clonedb/test

Production Database Server: 
  Name       : prod
  IP Address : 192.168.2.171
  ORACLE_HOME: /u01/app/oracle/product/11.2.0.2/db_1
  ORACLE_SID : PROD

CloneDB Database Server:
  Name       : test
  IP Address : 192.168.2.172
  ORACLE_HOME: /u01/app/oracle/product/11.2.0.2/db_1
  ORACLE_SID : TEST
  NFS Mount  : /u01/app/oracle/oradata/TEST

The database servers are running Oracle 11.2.0.2 (64-bit) on Oracle Enterprise Linux (OEL 5.5 64-bit). The Oracle installation is similar to that described here. The "clonedb" server is a software-only installation.

Related articles.

The Clone Perl Script

This article was originally written again 11gR2, where the only source of the "clone.pl" script was from the My Oracle Support (MOS) Note 1210656.1, which also documents its usage. I'd like to say a big thank you to Kevin Closson and Margaret Susairaj from Oracle for introducing me to the feature and helping me to get it up and running. You can see a short video presentation and video demo of CloneDB on Kevin Closson's blog here.

In later releases the Perl script is shipped in the "$ORACLE_HOME/rdbms/install" directory and has been renamed to "clonedb.pl" . Any reference in this article to "clone.pl" can substituted for "clonedb.pl" if you are using a later release.

NFS Server Setup

On the NFS server, create a directory as the copy-on-write location for the cloned instance.

# mkdir -p /u01/nfs_shares/clonedb/test

Export the directory as an NFS share by adding the following lines to the "/etc/exports" file.

/u01/nfs_shares/clonedb/test         *(rw,sync,no_wdelay,insecure,insecure_locks,no_root_squash)

Make sure the NFS service is available after reboot and restart the NFS service.

# chkconfig nfs on
# service nfs restart

Production Backup

We have to take an image copy of the database using RMAN. The backup should be placed in a location available to the server that will run the clone. In this case I am using a samba (CIFS) share for the "/host/backups/prod" location, but it could just as easily be an NFS mount.

$ rman target=/

configure controlfile autobackup off;
#sql 'alter database begin backup';
run {
   set nocfau;
   backup as copy database format '/host/backups/prod/%U' ;
}
#sql 'alter database end backup';

The MOS note suggests switching the database to backup mode during the backup, but this is not necessary.

Next, create a PFILE from the contents of the production SPFILE.

SQL> -- On production server as the SYS user.
SQL> CREATE PFILE='/host/backups/prod/initTEST.ora' FROM SPFILE;

Amend the contents of the PFILE to reflect the clone database. Here is the amended PFILE I used. In this case my original database name was PROD, so I have replaced all references to that database name with TEST.

TEST.__db_cache_size=205520896
TEST.__java_pool_size=25165824
TEST.__large_pool_size=4194304
TEST.__oracle_base='/u01/app/oracle'#ORACLE_BASE set from environment
TEST.__pga_aggregate_target=293601280
TEST.__sga_target=549453824
TEST.__shared_io_pool_size=0
TEST.__shared_pool_size=301989888
TEST.__streams_pool_size=4194304
*.audit_file_dest='/u01/app/oracle/admin/TEST/adump'
*.audit_trail='DB'
*.compatible='11.2.0.2.0'
*.control_files='/u01/app/oracle/oradata/TEST/control01.ctl','/u01/app/oracle/oradata/TEST/control02.ctl'
*.db_block_size=8192
*.db_create_file_dest='/u01/app/oracle/oradata/TEST/'
*.db_domain='WORLD'
*.db_name='TEST'
*.db_recovery_file_dest_size=4070572032
*.db_recovery_file_dest='/u01/app/oracle/fast_recovery_area'
*.diagnostic_dest='/u01/app/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=TESTXDB)'
*.event=''
*.memory_target=843055104
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.undo_tablespace='UNDOTBS1'
# Following parameter is also needed for 11.2.0.3 onward.
#*.clonedb=true

Database versions 11.2.0.3 onward include a new initialization parameter called CLONEDB that must be set to TRUE in the clone for the CloneDB functionality to work. Thanks to Marcin Przepiorowski for pointing out this change.

CloneDB Server Setup

Make sure the Direct NFS client is enabled for the Oracle home on the server that will run the clone.

$ cd $ORACLE_HOME/rdbms/lib
$ make -f ins_rdbms.mk dnfs_on

Make directories for the NFS mount point, along with some others needed by the TEST instance.

# su - oracle
$ mkdir -p $ORACLE_BASE/oradata/TEST
$ mkdir -p $ORACLE_BASE/fast_recovery_area/TEST
$ mkdir -p $ORACLE_BASE/admin/TEST/adump
$ mkdir -p $ORACLE_BASE/admin/TEST/dpdump

Add the following line into the "/etc/fstab" file so the share is mounted automatically on reboot.

nas1:/u01/nfs_shares/clonedb/test /u01/app/oracle/oradata/TEST  nfs  rw,bg,hard,nointr,tcp,vers=3,timeo=600,rsize=32768,wsize=32768,actimeo=0  0 0

Mount the backup share. If you are consistent with the UID of the OS "oracle" user the ownership and permissions should be fine.

# mount /u01/app/oracle/oradata/TEST

Move the PFILE to the "$ORACLE_HOME/dbs" directory.

# su - oracle
$ mv /host/backups/prod/initTEST.ora $ORACLE_HOME/dbs

Remove everything other than datafile image copies from the backup directory. If other file types are present, a later script will assume they are datafiles when creating the new controlfile. The contents of my backup directory is displayed below.

$ cd /host/backups/prod
$ ls -l
total 1662132
-rw-r----- 1 oracle vboxsf 362422272 Feb  4 10:07 data_D-PROD_I-153794047_TS-EXAMPLE_FNO-5_0nm3qgqb
-rw-r----- 1 oracle vboxsf 555753472 Feb  4 10:06 data_D-PROD_I-153794047_TS-SYSAUX_FNO-2_0mm3qgph
-rw-r----- 1 oracle vboxsf 744497152 Feb  4 10:06 data_D-PROD_I-153794047_TS-SYSTEM_FNO-1_0lm3qgoo
-rw-r----- 1 oracle vboxsf  78651392 Feb  4 10:07 data_D-PROD_I-153794047_TS-UNDOTBS1_FNO-3_0om3qgqq
-rw-r----- 1 oracle vboxsf   5251072 Feb  4 10:07 data_D-PROD_I-153794047_TS-USERS_FNO-4_0pm3qgqt
$

Set the following environment variables to the appropriate values for your setup.

$ export ORACLE_SID=TEST
$ export MASTER_COPY_DIR=/host/backups/prod
$ export CLONE_FILE_CREATE_DEST=/u01/app/oracle/oradata/TEST
$ export CLONEDB_NAME=TEST

Switch to the "/tmp" directory and run the clone Perl script, naming the correct "init.ora" file to start the instance and specifying name for the cloning script it will create.

$ # 11gR2.
$ cd /tmp
$ perl /u01/software/clone.pl $ORACLE_HOME/dbs/initTEST.ora crtdb.sql dbren.sql

$ # Later Releases.
$ cd /tmp
$ perl $ORACLE_HOME/rdbms/install/clonedb.pl $ORACLE_HOME/dbs/initTEST.ora crtdb.sql dbren.sql


Start SQL*Plus as SYSDBA and run the scripts created by the clone Perl script. The cloning script contains a generated CREATE CONTROLFILE command and calls to DBMS_DNFS.CLONEDB_RENAMEFILE to associate the copy-on-write location with the backup datafile.

$ sqlplus / as sysdba

@crtdb.sql
@dbren.sql

The following output shows you what to expect.

$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.2.0 Production on Wed Feb 2 21:39:34 2011

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> @crtdb.sql
SQL> SET FEEDBACK 1
SQL> SET NUMWIDTH 10
SQL> SET LINESIZE 80
SQL> SET TRIMSPOOL ON
SQL> SET TAB OFF
SQL> SET PAGESIZE 100
SQL> 
SQL> STARTUP NOMOUNT PFILE=/u01/app/oracle/oradata/TEST/initTEST.ora
ORACLE instance started.

Total System Global Area  839282688 bytes
Fixed Size                  2231128 bytes
Variable Size             629146792 bytes
Database Buffers          205520896 bytes
Redo Buffers                2383872 bytes
SQL> CREATE CONTROLFILE REUSE SET DATABASE TEST RESETLOGS
  2      MAXLOGFILES 32
  3      MAXLOGMEMBERS 2
  4      MAXINSTANCES 1
  5      MAXLOGHISTORY 908
  6  LOGFILE
  7    GROUP 1 '/u01/app/oracle/oradata/TEST/TEST_log1.log' SIZE 100M BLOCKSIZE 512,
  8    GROUP 2 '/u01/app/oracle/oradata/TEST/TEST_log2.log' SIZE 100M BLOCKSIZE 512
  9  DATAFILE
 10  '/host/backups/prod/data_D-PROD_I-153794047_TS-EXAMPLE_FNO-5_0nm3qgqb',
 11  '/host/backups/prod/data_D-PROD_I-153794047_TS-SYSAUX_FNO-2_0mm3qgph',
 12  '/host/backups/prod/data_D-PROD_I-153794047_TS-SYSTEM_FNO-1_0lm3qgoo',
 13  '/host/backups/prod/data_D-PROD_I-153794047_TS-UNDOTBS1_FNO-3_0om3qgqq',
 14  '/host/backups/prod/data_D-PROD_I-153794047_TS-USERS_FNO-4_0pm3qgqt'
 15  CHARACTER SET WE8DEC;

Control file created.

SQL> @dbren.sql
SQL> REM Rename clonedb files to local copy from backup
SQL> declare
  2  begin
  3  dbms_dnfs.clonedb_renamefile('/host/backups/prod/data_D-PROD_I-153794047_TS-EXAMPLE_FNO-5_0nm3qgqb' , '/u01/app/oracle/oradata/TEST/ora_data_TEST0.dbf');
  4  dbms_dnfs.clonedb_renamefile('/host/backups/prod/data_D-PROD_I-153794047_TS-SYSAUX_FNO-2_0mm3qgph' , '/u01/app/oracle/oradata/TEST/ora_data_TEST1.dbf');
  5  dbms_dnfs.clonedb_renamefile('/host/backups/prod/data_D-PROD_I-153794047_TS-SYSTEM_FNO-1_0lm3qgoo' , '/u01/app/oracle/oradata/TEST/ora_data_TEST2.dbf');
  6  dbms_dnfs.clonedb_renamefile('/host/backups/prod/data_D-PROD_I-153794047_TS-UNDOTBS1_FNO-3_0om3qgqq' , '/u01/app/oracle/oradata/TEST/ora_data_TEST3.dbf');
  7  dbms_dnfs.clonedb_renamefile('/host/backups/prod/data_D-PROD_I-153794047_TS-USERS_FNO-4_0pm3qgqt' , '/u01/app/oracle/oradata/TEST/ora_data_TEST4.dbf');
  8  end;
  9  /

PL/SQL procedure successfully completed.

SQL> 
SQL> REM open clone database
SQL> WHENEVER SQLERROR CONTINUE
SQL> alter database open resetlogs;

Database altered.

SQL> 
SQL> REM create any temp tablespaces needed
SQL> drop tablespace TEMP;
drop tablespace TEMP
*
ERROR at line 1:
ORA-12906: cannot drop default temporary tablespace


SQL> create temporary tablespace TEMP;
create temporary tablespace TEMP
*
ERROR at line 1:
ORA-01543: tablespace 'TEMP' already exists


SQL> 

If the backup is fuzzy it may need media recovery using the archived redo logs from production. You can do this using the following commands.

RECOVER DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL;
ALTER DATABASE OPEN RESETLOGS;

Once the scripts are complete you will have a functioning clone.

COLUMN df_name FORMAT A50
COLUMN ts_name FORMAT A10

SELECT t.name AS ts_name,
       d.name AS df_name,
       status
FROM   v$datafile d
       JOIN v$tablespace t ON t.ts# = d.ts#
ORDER BY t.name;

TS_NAME    DF_NAME                                            STATUS
---------- -------------------------------------------------- -------
EXAMPLE    /u01/app/oracle/oradata/TEST/ora_data_TEST0.dbf    ONLINE
SYSAUX     /u01/app/oracle/oradata/TEST/ora_data_TEST1.dbf    ONLINE
SYSTEM     /u01/app/oracle/oradata/TEST/ora_data_TEST2.dbf    SYSTEM
UNDOTBS1   /u01/app/oracle/oradata/TEST/ora_data_TEST3.dbf    ONLINE
USERS      /u01/app/oracle/oradata/TEST/ora_data_TEST4.dbf    ONLINE

SQL>

We can see the copy-on-write location doesn't contain a whole copy of the backup datafiles, just the changed blocks, using the "du" command. If listed using the "ls" command they show as full size.

$ du -k /host/backups/prod/*
354280	/host/backups/prod/data_D-DB11G_I-199362479_TS-EXAMPLE_FNO-5_1mmjkqp5
717512	/host/backups/prod/data_D-DB11G_I-199362479_TS-SYSAUX_FNO-2_1kmjkqmb
738012	/host/backups/prod/data_D-DB11G_I-199362479_TS-SYSTEM_FNO-1_1jmjkqku
563764	/host/backups/prod/data_D-DB11G_I-199362479_TS-UNDOTBS1_FNO-3_1lmjkqno
30764	/host/backups/prod/data_D-DB11G_I-199362479_TS-USERS_FNO-4_1nmjkqpv
$

$ du -k /u01/app/oracle/oradata/TEST/*.dbf
16	/u01/app/oracle/oradata/TEST/ora_data_TEST0.dbf
52	/u01/app/oracle/oradata/TEST/ora_data_TEST1.dbf
76	/u01/app/oracle/oradata/TEST/ora_data_TEST2.dbf
176	/u01/app/oracle/oradata/TEST/ora_data_TEST3.dbf
16	/u01/app/oracle/oradata/TEST/ora_data_TEST4.dbf
8832	/u01/app/oracle/oradata/TEST/TEST_ctl.dbf
$

Outstanding Issues

In 11gR2 the "clone.pl" script is still not bullet proof.

Considerations

Here are some things to consider before choosing to use this approach.

Clone DB has a sweet spot, where you need to create several short-lived clones quickly and you want to save space while you are doing it. It's not a blanket replacement for other cloning techniques.

For more information see:

Hope this helps. Regards Tim...

Back to the Top.