DEV Community

umzzil nng
umzzil nng

Posted on Originally published at oraerror.com

Oracle ORA-16001 Error: Causes and Solutions Complete Guide

ORA-16001: Database Already Open for Read-Only Access

ORA-16001 is an Oracle error that occurs when you attempt a write operation or try to change the open mode of a database that is already open in Read-Only mode. This error is most commonly encountered in Oracle Data Guard environments where a Physical Standby database is operating in Read-Only or Active Data Guard mode. Understanding the current database state before executing any commands is the key to resolving and preventing this error.


Top 3 Causes

1. Attempting Writes on a Data Guard Standby Database

The most frequent cause is trying to perform DML or DDL operations directly on a Physical Standby database that is open in Read-Only mode. Automation scripts that don't differentiate between Primary and Standby databases often trigger this error.

-- Check current database role and open mode first
SELECT NAME, OPEN_MODE, DATABASE_ROLE, DB_UNIQUE_NAME
FROM V$DATABASE;

-- Expected output on a Standby:
-- OPEN_MODE     = READ ONLY
-- DATABASE_ROLE = PHYSICAL STANDBY
Enter fullscreen mode Exit fullscreen mode

2. Attempting to Re-Open an Already Open Read-Only Database

Executing ALTER DATABASE OPEN or ALTER DATABASE OPEN READ WRITE on a database that is already open in Read-Only mode without first closing it will trigger ORA-16001. Oracle does not allow an in-place mode transition without a proper shutdown and restart cycle.

-- WRONG: This will cause ORA-16001 if DB is already READ ONLY
ALTER DATABASE OPEN READ WRITE;  -- ERROR if already open

-- CORRECT: Shutdown first, then reopen
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE OPEN READ WRITE;

-- Verify the change
SELECT NAME, OPEN_MODE FROM V$DATABASE;
Enter fullscreen mode Exit fullscreen mode

3. Incorrect Command Sequence in Active Data Guard (ADG) Environments

In Active Data Guard setups, the Standby database runs in READ ONLY WITH APPLY mode. Running commands out of sequence — such as trying to cancel recovery and open Read-Write without a proper switchover — causes ORA-16001.

-- Check MRP (Managed Recovery Process) status
SELECT PROCESS, STATUS, SEQUENCE#
FROM V$MANAGED_STANDBY
WHERE PROCESS = 'MRP0';

-- Correct sequence to restart Managed Recovery
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
ALTER DATABASE OPEN READ ONLY;
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE
    USING CURRENT LOGFILE DISCONNECT;

-- Verify
SELECT OPEN_MODE, DATABASE_ROLE FROM V$DATABASE;
Enter fullscreen mode Exit fullscreen mode

Quick Fix Solutions

Fix 1 — Perform a Switchover (Data Guard)

-- On PRIMARY: Verify switchover readiness
SELECT SWITCHOVER_STATUS FROM V$DATABASE;
-- Should show 'TO STANDBY'

-- On PRIMARY: Initiate switchover
ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY
    WITH SESSION SHUTDOWN;

-- On new PRIMARY (former Standby):
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY
    WITH SESSION SHUTDOWN;
ALTER DATABASE OPEN;

-- On new STANDBY: Resume Managed Recovery
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE
    DISCONNECT FROM SESSION;
Enter fullscreen mode Exit fullscreen mode

Fix 2 — Pre-check Script to Avoid the Error

DECLARE
    v_open_mode VARCHAR2(20);
    v_role      VARCHAR2(30);
BEGIN
    SELECT OPEN_MODE, DATABASE_ROLE
    INTO v_open_mode, v_role
    FROM V$DATABASE;

    IF v_open_mode = 'READ ONLY' THEN
        RAISE_APPLICATION_ERROR(-20001,
            'ERROR: DB is READ ONLY. Role: ' || v_role ||
            '. Writes are not allowed.');
    END IF;
    DBMS_OUTPUT.PUT_LINE('OK: ' || v_open_mode || ' | ' || v_role);
END;
/
Enter fullscreen mode Exit fullscreen mode

Prevention Tips

  • Always validate database state before running any scripts. Add a state-check block at the beginning of every automation or deployment script to detect Read-Only mode early and halt execution gracefully.

  • Use Role-Based Services in Data Guard to ensure applications automatically connect to the correct database based on its current role (Primary vs. Standby), preventing accidental write attempts on a Read-Only Standby.

-- Create a Read-Write service for Primary only
EXECUTE DBMS_SERVICE.CREATE_SERVICE(
    service_name => 'APP_RW',
    network_name => 'APP_RW');

-- Verify active services
SELECT NAME, NETWORK_NAME FROM DBA_SERVICES;
Enter fullscreen mode Exit fullscreen mode

Related Oracle Errors

Error Code Description
ORA-16000 DB open for read-only access (informational)
ORA-01109 Database not open
ORA-01507 Database not mounted
ORA-10456 Cannot open standby database; media recovery active
ORA-16014 Log cannot be archived; no available destinations

📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.

Top comments (0)