Creating a RAC Database Manually (without dbca)

Posted at Thursday, February 28, 2008
If you would like to by-pass the Database Configuration Assistant (dbca), you can use the following example - with appropriate alterations - to create your RAC databases. This example assumes that you already have a cluster with the appropriate clusterware and shared storage, etc. configured.

If not already present, create listeners on each node; for example:

On node1:

LISTENER_RAC1 =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT = 1525)(IP = FIRST))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.101)(PORT = 1525)(IP = FIRST))
)
)

On node2:

LISTENER_RAC2 =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT = 1525)(IP = FIRST))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.102)(PORT = 1525)(IP = FIRST))
)
)

I start with an area of shared storage for the files shared by the instances:

# mount | grep /u02/app/oracle
/dev/sdb1 on /u02/app/oracle type ocfs2 (rw,_netdev,heartbeat=local)

As you can see, I am using an ocfs2 filesystem for this purpose. I will create the necessary files here and create the appropriate symbolic links from each $ORACLE_HOME - this example does not use a shared $ORACLE_HOME.

Create the following files in your shared directory as appropriate: tnsnames.ora, sqlnet.ora, orapw${ORACLE_SID}, init.ora.

Example tnsnames.ora

LISTENER_RAC2 =
(address = (protocol = tcp)(host = rac2-vip)(port = 1525))


LISTENER_RAC1 =
(address = (protocol = tcp)(host = rac1-vip)(port = 1525))


JLC =
(DESCRIPTION =
(ADDRESS_LIST =
(address = (protocol = tcp)(host = rac1-vip)(port = 1525))
(address = (protocol = tcp)(host = rac2-vip)(port = 1525))
(LOAD_BALANCE = yes)
)
(CONNECT_DATA =
(SERVER = dedicated)
(SERVICE_NAME = jlc.colestock.test)
(failover_mode =
(type = select)
(method = basic)
(retries = 180)
(delay = 5)
)
)
)

LISTENERS_JLC =
(address_list =
(address = (protocol = tcp)(host = rac1-vip)(port = 1525))
(address = (protocol = tcp)(host = rac2-vip)(port = 1525))
)

JLC2 =
(DESCRIPTION =
(ADDRESS_LIST =
(address = (protocol = tcp)(host = rac2-vip)(port = 1525))
)
(CONNECT_DATA =
(SERVICE_NAME = jlc.colestock.test)
(INSTANCE_NAME = jlc2)
)
)

Example sqlnet.ora

NAMES.DIRECTORY_PATH= (TNSNAMES)


Example init.ora

*.db_name=jlc
*.db_block_size=8192
*.db_domain=colestock.test
*.service_names='jlc.colestock.test'
*.diagnostic_dest=/u02/app/oracle
jlc1.instance_name=jlc1
jlc2.instance_name=jlc2
*.memory_target=360M
*.control_files=("/u02/app/oradata01/jlc/control01.ctl","/u02/app/oradata02/jlc/control02.ctl")
jlc1.local_listener=LISTENER_RAC1
jlc2.local_listener=LISTENER_RAC2
*.remote_listener=LISTENERS_JLC
jlc1.thread=1
jlc2.thread=2
jlc1.undo_tablespace=UNDOTBS1
jlc2.undo_tablespace=UNDOTBS2
*.cluster_database=false
jlc1.instance_number=1
jlc2.instance_number=2
jlc1.instance_name=jlc1
jlc2.instance_name=jlc2
*.undo_management=auto
*.compatible='11.1.0'

Once the aforementioned files are present in your shared directory, create symbolical links to each $ORACLE_HOME; for example:

On node1:

# ls -lar $ORACLE_HOME/dbs
lrwxrwxrwx 1 oracle dba 29 Feb 27 22:28 spfilejlc1.ora -> /u02/app/oracle/spfilejlc.ora
lrwxrwxrwx 1 oracle dba 24 Feb 27 21:06 orapwjlc1 -> /u02/app/oracle/orapwjlc
lrwxrwxrwx 1 oracle dba 27 Feb 27 21:24 initjlc1.ora -> /u02/app/oracle/initjlc.ora


# ls -lar $TNS_ADMIN
lrwxrwxrwx 1 oracle dba 28 Feb 27 21:00 tnsnames.ora -> /u02/app/oracle/tnsnames.ora
lrwxrwxrwx 1 oracle dba 26 Feb 27 21:00 sqlnet.ora -> /u02/app/oracle/sqlnet.ora

On node2:

# ls -lar $ORACLE_HOME/dbs
lrwxrwxrwx 1 oracle dba 29 Feb 27 22:25 spfilejlc2.ora -> /u02/app/oracle/spfilejlc.ora
lrwxrwxrwx 1 oracle dba 24 Feb 27 21:03 orapwjlc2 -> /u02/app/oracle/orapwjlc
lrwxrwxrwx 1 oracle dba 27 Feb 27 20:29 initjlc2.ora -> /u02/app/oracle/initjlc.ora


# ls -lart $TNS_ADMIN
lrwxrwxrwx 1 oracle dba 28 Feb 27 20:45 tnsnames.ora -> /u02/app/oracle/tnsnames.ora
lrwxrwxrwx 1 oracle dba 26 Feb 27 20:49 sqlnet.ora -> /u02/app/oracle/sqlnet.ora

Notice I have created a symbolic link to an spfile which has yet to be created - we will create this after creating the database.

Create the database (editing script as appropriate for your environment):

create_db_jlc.sql

shutdown immediate;
startup nomount;

CREATE DATABASE
CONTROLFILE REUSE
MAXINSTANCES 32
MAXLOGHISTORY 10000
MAXLOGMEMBERS 5
MAXLOGFILES 64
DATAFILE '/u02/app/oradata01/jlc/system01.dbf' SIZE 400M
REUSE AUTOEXTEND ON NEXT 10240K MAXSIZE UNLIMITED
SYSAUX DATAFILE '/u02/app/oradata01/jlc/sysaux01.dbf' SIZE 400M
REUSE AUTOEXTEND ON NEXT 10240K MAXSIZE 5G
DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE
'/u02/app/oradata02/jlc/temp01.dbf' SIZE 100M REUSE
UNDO TABLESPACE "UNDOTBS1" DATAFILE
'/u02/app/oradata01/jlc/undotbs1_01.dbf' SIZE 200M REUSE
CHARACTER SET UTF8
LOGFILE GROUP 1 ('/u02/app/oradata01/jlc/redo_1_1a.dbf','/u02/app/oradata02/jlc/redo_1_1b.dbf') SIZE 100M REUSE,
GROUP 2 ('/u02/app/oradata01/jlc/redo_1_2a.dbf','/u02/app/oradata02/jlc/redo_1_2b.dbf') SIZE 100M REUSE;
exit;


sqlplus "/ as sysdba" @create_db_jlc.sql > create_db_jlc.log &

Run Data Dictionary Scripts:

create_dd.sql

@$ORACLE_HOME/rdbms/admin/catalog.sql
@$ORACLE_HOME/rdbms/admin/catproc.sql
@$ORACLE_HOME/rdbms/admin/catclust.sql
@$ORACLE_HOME/rdbms/admin/utlrp.sql
exit;


sqlplus "/ as sysdba" @create_dd.sql > create_dd.log &

Notice, this script represents the absolute minimum in terms of data dictionary scripts; add calls to other scripts as necessary.

Cluster enable the database and add additional instances:

add_jlc2.sql

create spfile='/u02/app/oracle/spfilejlc.ora' from pfile;
shutdown immediate;
startup;
alter system set cluster_database=true scope=spfile;
shutdown immediate;
startup;
alter database add logfile thread 2
group 3
('/u02/app/oradata01/jlc/redo_3_3a.dbf',
'/u02/app/oradata02/jlc/redo_3_3b.dbf') size 100M reuse,
group 4
('/u02/app/oradata01/jlc/redo_4_4a.dbf',
'/u02/app/oradata02/jlc/redo_4_4b.dbf') size 100M reuse;
alter database enable public thread 2;
create undo tablespace UNDOTBS2 datafile '/u02/app/oradata02/jlc/undotbs2_01.dbf' SIZE 200M;
exit;

After this, the result spfile's contents should look something like this:

jlc1.__db_cache_size=121634816
jlc2.__db_cache_size=121634816
jlc1.__java_pool_size=4194304
jlc2.__java_pool_size=4194304
jlc1.__large_pool_size=4194304
jlc2.__large_pool_size=4194304
jlc1.__oracle_base='/u03/app/oracle'#ORACLE_BASE set from environment
jlc2.__oracle_base='/u03/app/oracle'#ORACLE_BASE set from environment
jlc1.__pga_aggregate_target=150994944
jlc2.__pga_aggregate_target=150994944
jlc1.__sga_target=226492416
jlc2.__sga_target=226492416
jlc1.__shared_io_pool_size=0
jlc2.__shared_io_pool_size=0
jlc1.__shared_pool_size=88080384
jlc2.__shared_pool_size=88080384
jlc1.__streams_pool_size=0
jlc2.__streams_pool_size=0
*.cluster_database=TRUE
*.compatible='11.1.0'
*.control_files='/u02/app/oradata01/jlc/control01.ctl','/u02/app/oradata02/jlc/c
ontrol02.ctl'
*.db_block_size=8192
*.db_domain='colestock.test'
*.db_name='jlc'
*.diagnostic_dest='/u02/app/oracle'
jlc1.instance_name='jlc1'
jlc2.instance_name='jlc2'
jlc1.instance_number=1
jlc2.instance_number=2
jlc1.local_listener='LISTENER_RAC1'
jlc2.local_listener='LISTENER_RAC2'
*.memory_target=360M
*.remote_listener='LISTENERS_JLC'
*.service_names='jlc.colestock.test'
jlc1.thread=1
jlc2.thread=2
*.undo_management='auto'
jlc1.undo_tablespace='UNDOTBS1'
jlc2.undo_tablespace='UNDOTBS2'


Startup instance(s) added from their associated node(s):

# export ORACLE_SID=jlc2
# . oraenv
# sqlplus "/ as sysdba"
SQL> startup

Update srvctl:

update_srvctl.bsh

#!/bin/bash

srvctl add database -d jlc -o $ORACLE_HOME
srvctl add instance -d jlc -i jlc1 -n rac1
srvctl add instance -d jlc -i jlc2 -n rac2
srvctl enable database -d jlc
srvctl enable instance -d jlc -i jlc1
srvctl enable instance -d jlc -i jlc2


./update_srvctl.bsh

The files from this example are available here: create_rac_db.tar

Labels: