Pluggable Database 環境に慣れる（２）(Oracle Database 19c)

PDB環境に接続するユーザーと権限の管理を試します。

# Pluggable Databaseに接続する
  SYS ユーザーがローカル接続したデータベースは CDB になります。現在接続中のデータベースは SQL*Plus からであれば SHOW CON_ID コマンドや、SHOW CON_NAME コマンドで確認できます。CDB に接続している場合、CON_NAME には CDB\\$ROOT が出力されます。CON_ID は V\\$PDBS ビューの CON_ID 列と対応しています。

```SQL:
$ 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:
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:
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 を設定します。

```Shell:
$ 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:
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:
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:
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:
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:
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:
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:
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>
```