PDB環境に接続するユーザーと権限の管理を試します。
Pluggable Databaseに接続する
SYS ユーザーがローカル接続したデータベースは CDB になります。現在接続中のデータベースは SQL*Plus からであれば SHOW CON_ID コマンドや、SHOW CON_NAME コマンドで確認できます。CDB に接続している場合、CON_NAME には CDB\$ROOT が出力されます。CON_ID は V\$PDBS ビューの CON_ID 列と対応しています。
$ sqlplus / as sysdba
SQL> SHOW CON_ID;
CON_ID
------------------------------
1
SQL> SHOW CON_NAME;
CON_NAME
------------------------------
CDB$ROOT
SQL>
SQL> SELECT CON_ID, NAME FROM V$PDBS;
CON_ID NAME
---------- ------------------------------
2 PDB$SEED
3 PDB1
4 PDB2
接続先を PDB に切り替えるには ALTER SESSION SET CONTAINER 文を実行するか、リスナー経由で接続します。
SQL> ALTER SESSION SET CONTAINER=pdb2;
セッションが変更されました。
SQL> SHOW CON_ID;
CON_ID
------------------------------
4
SQL> SHOW CON_NAME;
CON_NAME
------------------------------
PDB2
SQL> SELECT CON_ID, NAME FROM V$PDBS;
CON_ID NAME
---------- ------------------------------
4 PDB2
CDB に戻る場合は接続先に CDB\$ROOT を指定します。
SQL> ALTER SESSION SET CONTAINER = CDB$ROOT;
セッションが変更されました。
SQL> SHOW CON_NAME;
CON_NAME
------------------------------
CDB$ROOT
リスナー経由で接続する場合にはサービス名を指定します。PDB を作成すると同名のサービスがリスナーに自動的に登録されます。
tnsnames.ora に PDB サービスに接続する記述を追加して接続します。
SID 指定では接続できないため、クライアントが SID を使う場合は listner.ora ファイルに USE_SID_AS_SERVICE_{listener_name} = ON を設定します。
$ lsnrctl status | grep pdb
サービス"pdb1"には、1件のインスタンスがあります。
サービス"pdb2"には、1件のインスタンスがあります。
サービス"pdb3"には、1件のインスタンスがあります。
$
$ sqlplus pdbadmin/{password}@pdb3
SQL*Plus: Release 19.0.0.0.0 - Production on 木 2月 20 00:52:03 2020
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
最終正常ログイン時間: 木 2月 20 2020 00:50:51 -05:00
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
に接続されました。
SQL>
PDB管理者の権限
CREATE PLUGGABLE DATABASE 文で作成したPDB管理者には PDB_DBA ロールが標準で付与されます。
SQL> ALTER SESSION SET CONTAINER=pdb3;
セッションが変更されました。
SQL> SELECT GRANTED_ROLE, DEFAULT_ROLE FROM DBA_ROLE_PRIVS WHERE GRANTEE='PDBADMIN';
GRANTED_ROLE DEF
------------------------------ ---
PDB_DBA YES
SQL> SELECT PRIVILEGE FROM DBA_SYS_PRIVS WHERE GRANTEE='PDB_DBA';
PRIVILEGE
----------------------------------------
CREATE PLUGGABLE DATABASE
CREATE SESSION
SQL>
標準では PDB_DBA ロールにはほとんど権限が付与されていませんので、管理者として接続してもほとんど作業はできません。
SQL> CREATE TABLE data1(c1 NUMBER);
CREATE TABLE data1(c1 NUMBER)
*
行1でエラーが発生しました。:
ORA-01031: 権限が不足しています
PDB_DBA ロールに追加のシステム権限やロール(例えば DBA)追加することで PDB 管理者に DBA 作業権限を付与できます。GRANT 文の CONTAINER 句にはユーザーに対するロール付与の範囲を指定できます。接続中の PDB(CURRENT)、または共通設定(ALL)を指定できます。
SQL> ALTER SESSION SET CONTAINER=pdb2;
セッションが変更されました。
SQL> GRANT DBA TO pdbadmin CONTAINER=CURRENT;
権限付与が成功しました。
PDB 作成時に ROLES 句を指定してロールを指定することもできます。
SQL> CREATE PLUGGABLE DATABASE pdb4 ADMIN USER pdbadmin IDENTIFIED BY {password} ROLES=(DBA);
プラガブル・データベースが作成されました。
共通ユーザー
マルチテナント環境のデータベース・ユーザーは共通ユーザーとローカルユーザーに分類されます。共通ユーザーは全 PDB で共有されるユーザー、ローカルユーザーは PDB 専用の管理者ユーザーです。
CDB と同時に作成されるユーザーはすべて共通ユーザーであり、CREATE PLUGGABLE DATABASE 文で指定する管理者はローカルユーザーです。DBA_USERS ビューの COMMON 列が YES のユーザーが共通ユーザーになります。下記は PDB に接続して DBA_USERS ビューを検索しています。PDBADMIN ユーザーだけが COMMON 列が NO になっています。
SQL> SELECT USERNAME, COMMON FROM DBA_USERS ORDER BY 1;
USERNAME COM
------------------------------ ---
ANONYMOUS YES
APPQOSSYS YES
AUDSYS YES
CTXSYS YES
DBSFWUSER YES
DBSNMP YES
DIP YES
GGSYS YES
GSMADMIN_INTERNAL YES
GSMCATUSER YES
GSMUSER YES
MDDATA YES
MDSYS YES
OJVMSYS YES
OLAPSYS YES
ORACLE_OCM YES
ORDDATA YES
ORDPLUGINS YES
ORDSYS YES
OUTLN YES
PDBADMIN NO
REMOTE_SCHEDULER_AGENT YES
SI_INFORMTN_SCHEMA YES
SYS YES
SYS$UMF YES
SYSBACKUP YES
SYSDG YES
SYSKM YES
SYSRAC YES
SYSTEM YES
WMSYS YES
XDB YES
XS$NULL YES
33行が選択されました。
新規に共通ユーザーを作成する場合は、初期化パラメーター common_user_prefix をユーザー名の先頭に指定します。このパラメーターは CREATE USER 文実行時にチェックされるので変更後も元々あった共通ユーザーは利用できます。CDB 接続時には共通ユーザーのみ作成できます。
SQL> CREATE USER user1 IDENTIFIED BY {password};
CREATE USER user1 IDENTIFIED BY {password}
*
行1でエラーが発生しました。:
ORA-65096: 共通ユーザーまたはロール名が無効です
SQL> SHOW PARAMETER common_user_prefix
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
common_user_prefix string C##
SQL> CREATE USER C##user1 IDENTIFIED BY {password} DEFAULT TABLESPACE system TEMPORARY TABLESPACE temp;
ユーザーが作成されました。
SQL> SELECT username, common FROM dba_users WHERE username LIKE 'C##%';
USERNAME COMMON
------------------------------ ----------
C##USER1 YES
共通ユーザーを使うと CDB だけでなく、全 PDB にも接続することができます。ただし共通ユーザーに対する権限は CDB と PDB で別々に管理されています。CDB に接続した状態でシステム権限を共通ユーザーに付与しても、PDB 内では使用できません。
SQL> GRANT CREATE SESSION TO C##USER1;
権限付与が成功しました。
SQL> CONNECT C##user1/{password}@pdb3
ERROR:
ORA-01017: invalid username/password; logon denied
警告: Oracleにはもう接続されていません。
SQL> CONNECT / AS SYSDBA
接続されました。
SQL> ALTER SESSION SET CONTAINER=pdb3;
セッションが変更されました。
SQL> GRANT CREATE SESSION TO C##user1;
権限付与が成功しました。
SQL> DISCONNECT;
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0との接続が切断されました。
SQL> CONNECT C##user1/{password}@pdb3
接続されました。
SQL>
共通ユーザーは PDB に接続した状態では削除できません。ユーザーの削除だけでなく、一部の操作は管理者権限に接続しても PDB に接続した状態では実行できません。
SQL> CONNECT / AS SYSDBA
接続されました。
SQL> ALTER SESSION SET CONTAINER=pdb3;
セッションが変更されました。
SQL> DROP USER C##user1;
DROP USER C##user1
*
行1でエラーが発生しました。:
ORA-65040: プラガブル・データベース内からの操作は許可されていません
共通プロファイル
ユーザー属性に設定するプロファイルも共通プロファイルとPDB固有のプロファイルを作成することができます。共通プロファイルも共通ユーザー名と同様に初期化パラメーターcommon_user_prefixの影響を受けます。
SQL> CREATE PROFILE profile1 LIMIT PASSWORD_LIFE_TIME 120;
CREATE PROFILE profile1 LIMIT PASSWORD_LIFE_TIME 120
*
行1でエラーが発生しました。:
ORA-65140: 共通プロファイル名が無効です
SQL> CREATE PROFILE C##profile1 LIMIT PASSWORD_LIFE_TIME 120;
プロファイルが作成されました。
SQL> ALTER USER C##user1 PROFILE C##profile1;
ユーザーが変更されました。
SQL> SELECT username, profile FROM DBA_USERS WHERE username='C##USER1';
USERNAME PROFILE
------------------------------ ------------------------------
C##USER1 C##PROFILE1
共通ユーザーのプロファイル属性はデフォルトでは CDB の値が利用されますが、PDB 毎に管理することもできます。
SQL> ALTER SESSION SET CONTAINER=pdb3;
セッションが変更されました。
SQL> SELECT username, profile FROM DBA_USERS WHERE username='C##USER1';
USERNAME PROFILE
------------------------------ ------------------------------
C##USER1 C##PROFILE1
SQL> CREATE PROFILE profile1 LIMIT PASSWORD_LIFE_TIME 120;
プロファイルが作成されました。
SQL> ALTER USER C##user1 PROFILE profile1;
ユーザーが変更されました。
SQL> SELECT username, profile FROM DBA_USERS WHERE username='C##USER1';
USERNAME PROFILE
------------------------------ ------------------------------
C##USER1 PROFILE1
SQL>