Oracle Data Guard Broker provides DGMGRL as its primary command-line management interface, while the DBMS_DG PL/SQL package enables several Data Guard Broker operations to be controlled programmatically from scripts and custom tools. https://docs.oracle.com/en/database/oracle/oracle-database/26/dgbkr/DBMS_DG.html
With Data Guard protection available at the individual Pluggable Database level, commonly referred to as DGPDB, an interesting automation question arises: Can we perform an individual DGPDB switchover using the DBMS_DG PL/SQL API instead of DGMGRL?
I tested this behavior in an Oracle AI Database 26ai DGPDB environment. The results demonstrate an important distinction between the database-level DBMS_DG switchover API and the PDB-level switchover operation provided by Data Guard Broker.
DGPDB Environment
The test environment consists of two primary CDBs participating in separate Broker configurations, with Data Guard protection configured between individual PDBs.
Source CDB : ORCLRUH
Source PDB : RUH_PDB
Target CDB : ORCLJED
Target PDB : JED_PDB
This architecture is important because DGPDB differs from traditional database-level Data Guard. Oracle documents that DGPDB protection uses two primary databases, with the source PDB protected by a target PDB in another CDB.
The source PDB was open in READ WRITE mode.
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 RUH_PDB READ WRITE NO
SQL>
The objective was to determine whether DBMS_DG could perform a role transition specifically between RUH_PDB and JED_PDB without performing a role transition of the complete CDB.
Testing DBMS_DG.SWITCHOVER from CDB$ROOT
The first test was performed while connected to CDB$ROOT as SYSDBA.
SQL> conn / as sysdba
Connected.
set serveroutput on;
declare
v_severity binary_integer;
v_retcode binary_integer;
begin
dbms_output.put_line('initiating dynamic database role transition to orcljed...');
execute immediate
'begin :1 := dbms_dg.switchover(db_name => ''orcljed'', severity => :2); end;'
using out v_retcode, out v_severity;
dbms_output.put_line('broker execution return code: ' || v_retcode);
dbms_output.put_line('broker validation severity state: ' || v_severity);
exception
when others then
dbms_output.put_line('programmatic switchover failed with error: ' || sqlerrm);
end;
/
Connected.
SQL>
initiating dynamic database role transition to orcljed...
broker execution return code: 16617
broker validation severity state: 16501
PL/SQL procedure successfully completed.
SQL>
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 RUH_PDB READ WRITE NO
SQL>
The PL/SQL call returned Broker status information, but no DGPDB role transition occurred. RUH_PDB remained READ WRITE on the source.
Checking the Available DBMS_DG Switchover Procedures
The next step was to verify exactly which switchover procedures are exposed by DBMS_DG in the installed environment.
SQL> set lines 200
col procedure_name format a45
select procedure_name
from dba_procedures
where owner='SYS'
and object_name='DBMS_DG'
and procedure_name like '%SWITCH%'
order by procedure_name;
PROCEDURE_NAME
---------------------------------------------
SWITCHOVER
SQL>
The result confirms that SWITCHOVER is the available switchover operation in DBMS_DG.
More importantly for this test, there is no separate PDB-specific switchover procedure exposed by the package. This leaves another possibility worth testing: perhaps executing DBMS_DG.SWITCHOVER while the current session is connected to the protected PDB causes Oracle to scope the operation to that PDB.
Testing from Within the Protected PDB
The source PDB was first confirmed to be open READ WRITE.
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 RUH_PDB READ WRITE NO
SQL>
The session was then changed to RUH_PDB. Before attempting the switchover, I verified whether DBMS_DG.SWITCHOVER was visible while connected to the PDB.
SQL> set serveroutput on
SQL> alter session set container=RUH_PDB;
set serveroutput on
declare
l_owner varchar2(30);
l_name varchar2(30);
l_line varchar2(4000);
begin
dbms_output.put_line('Container : ' || sys_context('USERENV','CON_NAME'));
select owner, object_name
into l_owner, l_name
from dba_procedures
where owner='SYS'
and object_name='DBMS_DG'
and procedure_name='SWITCHOVER'
and rownum=1;
dbms_output.put_line('Procedure found: ' || l_owner || '.' || l_name || '.SWITCHOVER');
dbms_output.put_line('No switchover executed.');
exception
when others then
dbms_output.put_line('ERROR: ' || sqlerrm);
end;
/
Session altered.
SQL>
Container : RUH_PDB
Procedure found: SYS.DBMS_DG.SWITCHOVER
No switchover executed.
PL/SQL procedure successfully completed.
SQL>
This confirms that DBMS_DG.SWITCHOVER is visible while the current container is RUH_PDB. The next step was to determine whether it can actually execute from that container.
Executing DBMS_DG.SWITCHOVER from RUH_PDB
The database-level switchover API was executed while the current container was RUH_PDB.
SQL> declare
l_severity binary_integer;
l_status binary_integer;
begin
2 3 4 5 dbms_output.put_line('Current container: ' || sys_context('USERENV','CON_NAME'));
dbms_output.put_line('Calling DBMS_DG.SWITCHOVER to ORCLJED...');
l_status := dbms_dg.switchover(
db_name => 'ORCLJED',
severity => l_severity
);
dbms_output.put_line('Return status : ' || l_status);
dbms_output.put_line('Severity : ' || l_severity);
exception
when others then
dbms_output.put_line('ERROR CODE : ' || sqlcode);
dbms_output.put_line('ERROR : ' || sqlerrm);
end;
/
Current container: RUH_PDB
Calling DBMS_DG.SWITCHOVER to ORCLJED...
ERROR CODE : -65040
ERROR : ORA-65040: Operation is not allowed from within a pluggable database.
PL/SQL procedure successfully completed.
SQL>
This result clearly establishes the limitation:
ORA-65040: Operation is not allowed from within a pluggable database.
The procedure is visible from the PDB, but the switchover operation itself cannot be executed from within the PDB. Therefore, changing the current container to RUH_PDB does not make the database-level DBMS_DG.SWITCHOVER operation PDB-aware.
What the Testing Confirms
The testing highlights a clear separation between database-level and DGPDB-level role transitions.
| Test | Result |
|---|---|
| DBMS_DG.SWITCHOVER from CDB$ROOT | Database-level operation |
| Target supplied to DBMS_DG.SWITCHOVER | Target database |
| DBMS_DG switchover procedures available | SWITCHOVER |
| Separate PDB switchover API found | No |
| DBMS_DG.SWITCHOVER visible from RUH_PDB | Yes |
| DBMS_DG.SWITCHOVER executable from RUH_PDB | No |
| Error returned | ORA-65040 |
| DGPDB switchover interface | Data Guard Broker/DGMGRL |
The key takeaway is that connecting to a PDB does not change the scope of DBMS_DG.SWITCHOVER.
The database-level API also does not provide the combination of target PDB and target database that is required to uniquely identify a DGPDB switchover target.
How DGPDB Switchover Is Different
Oracle defines a PDB switchover as a role reversal between a source PDB and its designated target PDB. During the operation, Broker validates both PDBs, ensures that the target is recovering the source redo stream, closes the source PDB, converts the source to the standby role, converts the target to the primary role, opens the new source PDB, and starts recovery on the former source.
This is different from a traditional database-level switchover, where the roles of the primary and standby databases themselves are reversed.
For DGPDB, Broker therefore needs to know both:
Target PDB : JED_PDB
Target Database : ORCLJED
That information is represented directly in the DGMGRL syntax.
Performing the DGPDB Switchover
Oracle specifically documents DGMGRL commands for performing PDB switchovers.
For this environment, the role transition is performed using:
DGMGRL> SWITCHOVER TO PLUGGABLE DATABASE JED_PDB AT ORCLJED;
Here:
JED_PDB = Target PDB that will assume the primary/source role
ORCLJED = Target database containing JED_PDB
This is exactly the information that cannot be expressed through the database-level DBMS_DG.SWITCHOVER interface.
Oracle’s documented syntax is:
DGMGRL> SWITCHOVER TO PLUGGABLE DATABASE <pdb_name> AT <target_db_unique_name>;
The specified PDB must exist in the target database and must already be configured as a DGPDB.
During the switchover, Data Guard Broker manages the required role transition activities and ultimately makes the target PDB the new source PDB.
Automation Consideration
DBMS_DG remains valuable for programmatically managing and monitoring many Data Guard Broker operations. Oracle specifically describes these APIs as a mechanism for controlling Broker configurations from scripts and batch programs.
However, the tests demonstrate that the database-level SWITCHOVER API cannot simply be reused for an individual DGPDB switchover.
For automated DGPDB role transitions, DGMGRL can instead be incorporated into shell scripts or other orchestration frameworks while using the PDB-specific Broker command:
DGMGRL> SWITCHOVER TO PLUGGABLE DATABASE JED_PDB AT ORCLJED;
Conclusion
DBMS_DG.SWITCHOVER operates at the database level and cannot be executed from within a PDB, as confirmed by ORA-65040. For an individual DGPDB switchover, Data Guard Broker through the PDB-specific DGMGRL command remains the appropriate interface.