As you might know, RO (Read Only) dbhome was introduced in Oracle 18c and became default configuration in Oracle 21c. Oracle came back with RW (Read Write) dbhome as default configuration in 23ai. It might be interesting to know how we can check if the oracle dbhome is RO (Read Only) or RW (Read Write). I had to recently look for it and just wanted to share it through this blog.

Environment

For my test I used a FREE Oracle 23ai version. Here are my ORACLE_HOME and my ORACLE_BASE environment:

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] echo $ORACLE_HOME
/opt/oracle/product/23ai/dbhomeFree

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] echo $ORACLE_BASE
/opt/oracle

We know that for RW dbhome the dbs folder will be used in $ORACLE_HOME and for RO in $ORACLE_BASE.

ORACLE_BASE_HOME will be $ORACLE_HOME for RW and $ORACLE_BASE/homes/<HOME_NAME> for RO.

I did not activate RO on my dbhome, so I should not have so far any dbs or homes directory in my $ORACLE_BASE:

oracle@vmdmkdev:~/ [rdbms2300] ls $ORACLE_BASE
admin  audit  cfgtoollogs  diag  oraInventory  product

ROOH stands for Read Only Oracle HOME.

Activate ROOH

I will active ROOH for my dbhome.

oracle@vmdmkdev:~/ [rdbms2300] roohctl -enable
Enabling Read-Only Oracle home.
Cannot enable Read-Only Oracle home in a configured Oracle home.
The Oracle Home is configured with databases 'FREE'.

I still have my FREE instance database using the dbhome. I have just updated oratab file to comment the database.

oracle@vmdmkdev:~/ [rdbms2300] vi /etc/oratab

And ran roohctl command again, which this time will be successful.

oracle@vmdmkdev:~/ [rdbms2300] roohctl -enable
Enabling Read-Only Oracle home.
Update orabasetab file to enable Read-Only Oracle home.
Orabasetab file has been updated successfully.
Create bootstrap directories for Read-Only Oracle home.
Bootstrap directories have been created successfully.
Bootstrap files have been processed successfully.
Bootstrap files have been processed successfully.
Read-Only Oracle home has been enabled successfully.
Check the log file /opt/oracle/cfgtoollogs/roohctl/roohctl-251003PM023449.log for more details.

Now I have got a homes folder in $ORACLE_BASE as well as a dbs one.

oracle@vmdmkdev:~/ [rdbms2300] ls $ORACLE_BASE
admin  audit  cfgtoollogs  dbs  diag  homes  oraInventory  product

Contents of homes folder:

oracle@vmdmkdev:~/ [rdbms2300] ls $ORACLE_BASE/homes
OraDBHome23aiFree
oracle@vmdmkdev:~/ [rdbms2300] ls $ORACLE_BASE/homes/OraDBHome23aiFree/
assistants  dbs  drdaas  hs  install  mgw  network  rdbms
oracle@vmdmkdev:~/ [rdbms2300] ls $ORACLE_BASE/homes/OraDBHome23aiFree/dbs
oracle@vmdmkdev:~/ [rdbms2300]

My dbs folder in $ORACLE_HOME remains, of course, unchanged:

oracle@vmdmkdev:~/ [rdbms2300] cdh
oracle@vmdmkdev:/opt/oracle/product/23ai/dbhomeFree/ [rdbms2300] cd dbs
oracle@vmdmkdev:/opt/oracle/product/23ai/dbhomeFree/dbs/ [rdbms2300] ls
hc_FREE.dat  init.ora  lkFREE_SITE1  orapwFREE  spfileFREE.ora

Deactivate ROOH again

Let’s deactivate ROOH again and make the Oracle Home RW again to start all the tests.

oracle@vmdmkdev:/opt/oracle/product/23ai/dbhomeFree/dbs/ [rdbms2300] roohctl -disable
Disabling Read-Only Oracle home.
Update orabasetab file to disable Read-Only Oracle home.
Orabasetab file has been updated successfully.
Read-Only Oracle home has been disabled successfully.
Check the log file /opt/oracle/cfgtoollogs/roohctl/roohctl-251003PM024030.log for more details.

dbs folder in $ORACLE_BASE will remain unchanged.

oracle@vmdmkdev:/opt/oracle/product/23ai/dbhomeFree/dbs/ [rdbms2300] cd $ORACLE_BASE
oracle@vmdmkdev:/opt/oracle/ [rdbms2300] ls
admin  audit  cfgtoollogs  dbs  diag  homes  oraInventory  product

Check dbhome status with orabasehome binary

There is a binary file, orabasehome, stored in $ORACLE_HOME/bin which will tell me if my Oracle Home is RO or RW. It will just provide the value of ORACLE_BASE_HOME. So either $ORACLE_HOME folder if it is a RW dbhome or $ORACLE_BASE/homes/<HOME_NAME> folder if it is a RO dbhome.

oracle@vmdmkdev:/opt/oracle/dbs/ [rdbms2300] $ORACLE_HOME/bin/orabasehome
/opt/oracle/product/23ai/dbhomeFree
oracle@vmdmkdev:/opt/oracle/dbs/ [rdbms2300]

The binary file will display in my case $ORACLE_HOME, which is correct.

Start the database

I tested instance startup with file either in $ORACLE_HOME/dbs or $ORACLE_BASE/dbs folder.

oracle@vmdmkdev:/opt/oracle/dbs/ [FREE (CDB$ROOT)] sqh

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Fri Oct 3 14:49:46 2025
Version 23.5.0.24.07

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

Connected to an idle instance.

SQL> startup
ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance
ORACLE instance started.

Total System Global Area 1070721856 bytes
Fixed Size		    5368640 bytes
Variable Size		  335544320 bytes
Database Buffers	  725614592 bytes
Redo Buffers		    4194304 bytes
Database mounted.
Database opened.

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

Database is starting correctly.

I moved the instance file from $ORACLE_HOME/dbs to $ORACLE_BASE/dbs:

oracle@vmdmkdev:/opt/oracle/dbs/ [FREE (CDB$ROOT)] ls -ltrh $ORACLE_HOME/dbs
total 18M
-rw-r-----. 1 oracle oinstall 3.1K May 14  2015 init.ora
lrwxrwxrwx. 1 oracle oinstall   38 Sep 26  2024 orapwFREE -> /opt/oracle/admin/FREE/pfile/orapwFREE
-rw-r-----. 1 oracle oinstall   24 Sep 26  2024 lkFREE_SITE1
-rw-r-----. 1 oracle oinstall 4.5K Oct  3 14:49 spfileFREE.ora
-rw-r-----. 1 oracle oinstall  18M Oct  3 14:59 snapcf_FREE.f
-rw-rw----. 1 oracle oinstall 1.6K Oct  3 15:06 hc_FREE.dat

oracle@vmdmkdev:/opt/oracle/dbs/ [FREE (CDB$ROOT)] ls -ltrh $ORACLE_BASE/dbs
total 0
oracle@vmdmkdev:/opt/oracle/dbs/ [FREE (CDB$ROOT)] mv $ORACLE_HOME/dbs/* $ORACLE_BASE/dbs

oracle@vmdmkdev:/opt/oracle/dbs/ [FREE (CDB$ROOT)] ls -ltrh $ORACLE_HOME/dbs
total 0
oracle@vmdmkdev:/opt/oracle/dbs/ [FREE (CDB$ROOT)] ls -ltrh $ORACLE_BASE/dbs
total 18M
-rw-r-----. 1 oracle oinstall 3.1K May 14  2015 init.ora
lrwxrwxrwx. 1 oracle oinstall   38 Sep 26  2024 orapwFREE -> /opt/oracle/admin/FREE/pfile/orapwFREE
-rw-r-----. 1 oracle oinstall   24 Sep 26  2024 lkFREE_SITE1
-rw-r-----. 1 oracle oinstall 4.5K Oct  3 14:49 spfileFREE.ora
-rw-r-----. 1 oracle oinstall  18M Oct  3 14:59 snapcf_FREE.f
-rw-rw----. 1 oracle oinstall 1.6K Oct  3 15:06 hc_FREE.dat

Starting the database would fail:

oracle@vmdmkdev:/opt/oracle/dbs/ [FREE (CDB$ROOT)] sqh

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Fri Oct 3 15:18:36 2025
Version 23.5.0.24.07

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

Connected to an idle instance.

SQL> startup
ORA-01078: failure in processing system parameters
LRM-00109: could not open parameter file '/opt/oracle/product/23ai/dbhomeFree/dbs/initFREE.ora'
SQL>

So Oracle is looking only for instance file in $ORACLE_HOME/dbs when configured in RW mode, which makes sense.

I moved database’s instance files again to $ORACLE_HOME/dbs, and delete $ORACLE_BASE/dbs and $ORACLE_BASE/homes.

oracle@vmdmkdev:/opt/oracle/ [FREE (CDB$ROOT)] mv $ORACLE_BASE/dbs/* $ORACLE_HOME/dbs/
oracle@vmdmkdev:/opt/oracle/ [FREE (CDB$ROOT)] ls $ORACLE_BASE/dbs/
oracle@vmdmkdev:/opt/oracle/ [FREE (CDB$ROOT)] ls $ORACLE_HOME/dbs/
hc_FREE.dat  init.ora  lkFREE_SITE1  orapwFREE  snapcf_FREE.f  spfileFREE.ora
oracle@vmdmkdev:/opt/oracle/ [FREE (CDB$ROOT)] rmdir $ORACLE_BASE/dbs/
oracle@vmdmkdev:/opt/oracle/ [FREE (CDB$ROOT)] rm -rf $ORACLE_BASE/homes

Activate ROOH again

I activated ROOH for the dbhome and checked dbs and homes folders to be created again.

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] roohctl -enable
Enabling Read-Only Oracle home.
Update orabasetab file to enable Read-Only Oracle home.
Orabasetab file has been updated successfully.
Create bootstrap directories for Read-Only Oracle home.
Bootstrap directories have been created successfully.
Bootstrap files have been processed successfully.
Bootstrap files have been processed successfully.
Read-Only Oracle home has been enabled successfully.
Check the log file /opt/oracle/cfgtoollogs/roohctl/roohctl-251003PM032952.log for more details.

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] ls -l $ORACLE_BASE | grep -iE 'dbs|homes'
drwxr-x---.  2 oracle oinstall    6 Oct 10 15:39 dbs
drwxr-x---.  3 oracle oinstall   31 Oct 10 15:39 homes
oracle@vmdmkdev:~/ [FREE (CDB$ROOT)]

Check dbhome status with orabasehome binary

Binary file is now showing $ORACLE_BASE/homes/HOME_NAME, so RO is really activated on my dbhome.

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] $ORACLE_HOME/bin/orabasehome
/opt/oracle/homes/OraDBHome23aiFree
oracle@vmdmkdev:~/ [FREE (CDB$ROOT)]

Start the database

Starting the database would fail, as there is no instance file in $ORACLE_BASE/dbs folder.

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] sqh

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Fri Oct 3 15:30:55 2025
Version 23.5.0.24.07

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

Connected to an idle instance.

SQL> startup
ORA-01078: failure in processing system parameters
LRM-00109: could not open parameter file '/opt/oracle/dbs/initFREE.ora'
SQL>

As expected…

By the way, the inventory.xml file is not displaying anything about RW or RO.

Let’s move the instance files from $ORACLE_HOME/dbs to $ORACLE_BASE/dbs:

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] ls -l $ORACLE_BASE/dbs
total 0
oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] ls -l $ORACLE_HOME/dbs
total 18340
-rw-rw----. 1 oracle oinstall     1544 Oct  3 15:06 hc_FREE.dat
-rw-r-----. 1 oracle oinstall     3079 May 14  2015 init.ora
-rw-r-----. 1 oracle oinstall       24 Sep 26  2024 lkFREE_SITE1
lrwxrwxrwx. 1 oracle oinstall       38 Sep 26  2024 orapwFREE -> /opt/oracle/admin/FREE/pfile/orapwFREE
-rw-r-----. 1 oracle oinstall 18759680 Oct  3 14:59 snapcf_FREE.f
-rw-r-----. 1 oracle oinstall     4608 Oct  3 14:49 spfileFREE.ora

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] mv $ORACLE_HOME/dbs/* $ORACLE_BASE/dbs

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] ls -l $ORACLE_BASE/dbs
total 18340
-rw-rw----. 1 oracle oinstall     1544 Oct  3 15:06 hc_FREE.dat
-rw-r-----. 1 oracle oinstall     3079 May 14  2015 init.ora
-rw-r-----. 1 oracle oinstall       24 Sep 26  2024 lkFREE_SITE1
lrwxrwxrwx. 1 oracle oinstall       38 Sep 26  2024 orapwFREE -> /opt/oracle/admin/FREE/pfile/orapwFREE
-rw-r-----. 1 oracle oinstall 18759680 Oct  3 14:59 snapcf_FREE.f
-rw-r-----. 1 oracle oinstall     4608 Oct  3 14:49 spfileFREE.ora
oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] ls -l $ORACLE_HOME/dbs
total 0
oracle@vmdmkdev:~/ [FREE (CDB$ROOT)]

And database can be started:

oracle@vmdmkdev:~/ [FREE (CDB$ROOT)] sqh

SQL*Plus: Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems on Fri Oct 3 15:48:23 2025
Version 23.5.0.24.07

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

Connected to an idle instance.

SQL> startup
ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance
ORACLE instance started.

Total System Global Area 1070721856 bytes
Fixed Size		    5368640 bytes
Variable Size		  335544320 bytes
Database Buffers	  725614592 bytes
Redo Buffers		    4194304 bytes
Database mounted.
Database opened.
SQL>

To wrap up…

If dbhome in RW or RO it looks in appropriate dbs directory, $ORACLE_HOME for RW and $ORACLE_BASE for RO.
Oracle inventory will not give us more details about if the Oracle dbhome is RW or RO.
orabasehome binary is the solution to know if the Oracle dbhome is in RW or RO.