はじめに
環境変数ORACLE_PDB_SIDを使用すると、OS認証でSQL*Plusから直接PDBに接続できます。
この環境変数を使用する場合には注意点があります。
- ORACLE_PDB_SIDで直接PDBに接続できるのは、SYS, SYSTEMユーザーのみ
- rmanのOS認証を利用した接続もORACLE_PDB_SIDの動作対象になる
- 存在しないPDB名をORACLE_PDB_SIDに設定すると、CDB$ROOTに接続される
- ORACLE_PDB_SIDを設定したままSQL*Plusでデータベースを起動後に、SYS, SYSTEMユーザでNet*Service接続するとPDBに接続される
特に注意したいのは、4つ目の「ORACLE_PDB_SIDを設定したままSQL*Plusでデータベースを起動後に、SYS, SYSTEMユーザでNet*Service接続するとPDBに接続される」点です。
以下、Oracle Database 19cで検証した結果をもとに記載しています。
ORACLE_PDB_SIDの動作の仕組み
ORACLE_PDB_SIDで指定したPDBに接続される動作は、CDB$ROOTに定義されているログオントリガー DBMS_SET_PDBによるものです。
DBMS_SET_PDBはOracle標準のSYS所有のログオントリガーです。
ログオン処理で一度CDB$ROOTに接続 → DBMS_SET_PDBトリガーでセッションのカレントコンテナを変更(alter session set container)という動作になります。
SQL> set pagesize 50000
SQL> set linesize 100
SQL> set long 1048576
SQL> set longchunksize 1048576
SQL> select dbms_metadata.get_ddl('TRIGGER', 'DBMS_SET_PDB', 'SYS') from dual;
DBMS_METADATA.GET_DDL('TRIGGER','DBMS_SET_PDB','SYS')
----------------------------------------------------------------------------------------------------
CREATE OR REPLACE NONEDITIONABLE TRIGGER "SYS"."DBMS_SET_PDB" after logon on database
WHEN (user = 'SYS' or user = 'SYSTEM') declare
pdb_name varchar2(64);
begin
DBMS_SYSTEM.get_env ('ORACLE_PDB_SID', pdb_name);
if(pdb_name is not null)
then
EXECUTE IMMEDIATE 'alter session set container = ' || '"' || pdb_name
|| '"';
end if;
exception
when others then
NULL;
end dbms_set_pdb;
ALTER TRIGGER "SYS"."DBMS_SET_PDB" ENABLE
DBMS_SET_PDBトリガーを無効化すると、常にCDB$ROOTに接続されます。
1. ORACLE_PDB_SIDで直接PDBに接続できるのは、SYS, SYSTEMユーザーのみ
DBMS_SET_PDBのDDLを見ると、動作対象はSYS, SYSTEMユーザーであることがわかります。
共通ユーザーc##adminでは、常にCDB$ROOTに接続されることを確認しています。
共通ユーザーの作成
$ sqlplus / as sysdba
SQL> alter session set container = CDB$ROOT;
SQL> create user c##admin identified by admin_password container = all;
SQL> grant create session to c##admin container = all;
SQL> exit
SYSユーザーのローカル接続
$ export ORACLE_PDB_SID=PDB1_1
$ sqlplus -S / as sysdba << EOF
> show con_name
> EOF
CON_NAME
------------------------------
PDB1_1
c##adminユーザーのローカル接続
$ export ORACLE_PDB_SID=PDB1_1
$ sqlplus -S c##admin/admin_password << EOF
> show con_name
> EOF
CON_NAME
------------------------------
CDB$ROOT
2. rmanのOS認証を利用した接続もORACLE_PDB_SIDの動作対象になる
ORACLE_PDB_SIDはSQL*Plusだけでなく、RMANで接続した場合(rman target / や rman target sys/<sys_password>)も動作対象になります。
$ export ORACLE_PDB_SID=PDB1_1
$ rman target /
Recovery Manager: Release 19.0.0.0.0 - Production on Thu Jun 11 08:24:39 2026
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.
connected to target database: CDB1:PDB1_1 (DBID=4053075928)
CDB$ROOTに接続した場合は、"connected to target database: CDB1"と出力されます。
今回はPDB1_1に接続されたので、"connected to target database: CDB1:PDB1_1"と出力されています。
3. 存在しないPDB名をORACLE_PDB_SIDに設定すると、CDB$ROOTに接続される
存在しないPDBをORACLE_PDB_SIDに指定してOS認証で接続した場合、alter sessionが失敗するため、CDB$ROOTに接続されます。
$ export ORACLE_PDB_SID=PDB1_2
$ sqlplus -S / as sysdba << EOF
> show con_name
> show pdbs
> EOF
CON_NAME
------------------------------
CDB$ROOT
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1_1 READ WRITE NO
4. ORACLE_PDB_SIDを設定したままSQL*Plusでデータベースを起動後に、SYS, SYSTEMユーザでNet*Service接続するとPDBに接続される
SYSやSYSTEMユーザ限定になりますが、非常に注意する内容です。
Net*Service経由でもPDBに接続されるようになると、接続元(クライアント側)のORACLE_PDB_SIDが設定されていなくてもPDBに接続されるようになります。
DBMS_SET_PDBトリガーを無効にするとCDB$ROOTに接続できるようになることから、このトリガーが原因であることが特定できています。
※ 下記例のcdb1はCDB$ROOTへのデフォルトサービス名です。
$ unset ORACLE_PDB_SID
$ sqlplus -S / as sysdba << EOF
> shutdown immediate
> EOF
$ export ORACLE_PDB_SID=PDB1_1
$ sqlplus -S / as sysdba << EOF
> startup
> EOF
$ unset ORACLE_PDB_SID
$ sqlplus -S sys/sys_password@listener_ip/cdb1 as sysdba << EOF
> show con_name
> EOF
CON_NAME
------------------------------
PDB1_1
rmanでNet*Service経由で接続するとPDBに接続されるため、CDB$ROOTに接続して行う操作が実行できなくなります。
$ unset ORACLE_PDB_SID
$ rman target sys/sys_password@listener_ip/cdb1
Recovery Manager: Release 19.0.0.0.0 - Production on Thu Jun 11 08:34:50 2026
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.
connected to target database: CDB1:PDB1_1 (DBID=4053075928)
Clusterware環境での影響
Oracle Restart、RAC One Node、RAC環境において、ORACLE_PDB_SIDを設定した状態で
- srvctl start database
- srvctl stop database
- srvctl relocate database
を実行した場合は、本事象を再現しませんでした(検証済)。
対処法
本事象が発生した場合は、以下のいずれかで解消できます。
- ORACLE_PDB_SIDを未設定にしてOracle Databaseを再起動する
$ unset ORACLE_PDB_SID
$ sqlplus / as sysdba
SQL> shutdown immediate
SQL> startup
- DBMS_SET_PDBトリガーを(一時的)に無効化する
$ unset ORACLE_PDB_SID
$ sqlplus / as sysdba
SQL> alter trigger sys.dbms_set_pdb disable;
※ DBMS_SET_PDBはOracle標準トリガーであるため、本番環境では十分な検証を行ったうえで実施してください。