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

Oracle Database 20cのマニュアルが公開され、Oracle CloudではPreview版を利用できるようになりました。Oracle Database 20cでは遂にマルチテナント構成（CDB/PDB構成）が必須になりました。[Oracle Database 20c Upgrade Guide](https://docs.oracle.com/en/database/oracle/oracle-database/20/upgrd/behavior-changes-deprecated-desupport-oracle-database.html#GUID-3BAFD95E-4D00-4F0F-BC80-6064F497F878) には以下の記述があります。

> 9 Behavior Changes, Deprecated and Desupported Features for Oracle Database
> Desupport of Non-CDB Oracle Databases
> Starting with Oracle Database 20c, installation of non-CDB Oracle Database architecture is no longer supported.
> The non-CDB architecture was deprecated in Oracle Database 12c. It is desupported in Oracle Database 20c. Oracle Universal Installer can no longer be used to create non-CDB Oracle Database instances.

このためあらためてマルチテナント構成を復習することにしました。
マルチテナント構成ではデータベースを Container Database (CDB) と Pluggable Database (PDB) に分割して構成します。従来のデータベースに相当する部分をCDBと呼びます。一方でアプリケーションが接続して使用するデータベースがPDBです。PDBはCDB内に複数作成されますが、相互に参照や更新はできず、アプリケーションにとっては独立したデータベースに見えます。PDB は従来のデータベースとほぼ同じ環境が提供されていますが、異なる部分もあります。
・制御ファイルやREDOログファイルは、CDBが管理します。
・PROFILE, USER, ROLEなどはPDB単位に管理できます。
・初期化パラメーターはPDBでは変更できないものがあります。PDBの初期化パラメーターはOS上のファイルには出力されません。
・表領域はPDB単位に作成されます。UNDO表領域はPDB単位／CDB単位を選択できます。
・CDBとPDBでは表領域のデータファイルは共有しません。
・PDB作成時にPDB管理者名を決めますが、ユーザー名は任意です。

# CDBを作る
マルチテナント環境の使用はデータベース作成時に決定され、後から変更できません。
Database Configuration Assistant (DBCA) を使ってデータベースを作成する場合には下記の画面で設定します。
![DBCA](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181284/773ee8b1-35a8-6b5d-6916-bc16f78005ec.png)


「コンテナ・データベースとして作成」をチェックするとマルチテナント構成のデータベース（CDB）が作成されます。同時にPDBも作成することができますが、PDBは後から作成／削除できます。
　DBCAから生成されるデータベース作成時に実行されるCREATE DATABASE文は以下の通りです（各種設定はデフォルト）。

```
CREATE DATABASE "O19D"
MAXINSTANCES 8
MAXLOGHISTORY 1
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 1024
DATAFILE SIZE 700M AUTOEXTEND ON NEXT  10240K MAXSIZE UNLIMITED
EXTENT MANAGEMENT LOCAL
SYSAUX DATAFILE SIZE 550M AUTOEXTEND ON NEXT  10240K MAXSIZE UNLIMITED
SMALLFILE DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE SIZE 20M AUTOEXTEND ON NEXT  640K MAXSIZE UNLIMITED
SMALLFILE UNDO TABLESPACE "UNDOTBS1" DATAFILE  SIZE 200M AUTOEXTEND ON NEXT  5120K MAXSIZE UNLIMITED
CHARACTER SET AL32UTF8
NATIONAL CHARACTER SET AL16UTF16
LOGFILE GROUP 1  SIZE 200M,
GROUP 2  SIZE 200M,
GROUP 3  SIZE 200M
USER SYS IDENTIFIED BY "&&sysPassword" USER SYSTEM IDENTIFIED BY "&&systemPassword"
enable pluggable database LOCAL UNDO ON;
```
　
最後の行にある「enable pluggable database」がマルチテナント構成を有効にする宣言です。そのあとにある「LOCAL UNDO ON」は、DBCAで「PDB用のローカルUNDO表領域の使用(L)」をチェックした場合に指定されます。

# PDBを作る
従来と同様にCDBの管理者はSYSで、管理者権限で接続するには「AS SYSDBA」宣言が必要です。PDBを作成するにはCREATE PLUGGABLE DATABASE文を実行します。もっとも簡単な方法はPDB$SEEDと呼ばれるテンプレートから作成する方法です。CREATE PLUGGABLE DATABASEシステム権限を持つユーザーであればSYS/SYSTEMユーザー以外でもPDBを作成できます。

```SQL: PDB 作成
SQL> CREATE PLUGGABLE DATABASE pdb3 ADMIN USER pdbadmin IDENTIFIED BY {password} ;

プラガブル・データベースが作成されました。

```

pdb3はPDBの名前です。pdbadminはPDB自身の管理者ユーザー名です。このユーザーはCDBには作成されません。
　CDBのデータファイルがOS標準のファイルシステム上に作成されている場合やASMを使っていない場合は、CREATE PLUGGABLE DATABASE文にFILE_NAME_CONVERTオプションの指定が必要になる場合があります。このパラメーターは、PDBが使用する表領域のデータファイルのパスを決定する際に使われます。

```SQL: PDB 作製
SQL> CREATE PLUGGABLE DATABASE pdb3 ADMIN USER pdbadmin IDENTIFIED BY {password};
CREATE PLUGGABLE DATABASE pdb3 ADMIN USER pdbadmin IDENTIFIED BY {password}
                                                                           *
行1でエラーが発生しました。:
ORA-65016: FILE_NAME_CONVERTを指定する必要があります


SQL> CREATE PLUGGABLE DATABASE pdb3 ADMIN USER pdbadmin IDENTIFIED BY {password} 
  FILE_NAME_CONVERT=('O19D', 'PDB3');

プラガブル・データベースが作成されました。

```

PDB管理者ユーザー名はDBCAを使ってあらかじめPDBを作成した場合にはPDBADMINが指定されますが、別の名前でも構いません。ただしSYSやSYSTEMは使うことができません。

# PDBのデータファイル
 PLUGGABLE DATABASE を作成すると、SYSTEM/SYSAUX 等の表領域とデータファイルが別途作成されます。これら PDB 用のデータファイルは、CDB の DBA_DATA_FILES ビューには現れません。PDBに接続してDBA_DATA_FILES ビューを参照するか、CDB_DATA_FILES / CDB_TEMP_FILES ビューを参照します。これらのビューにはCON_ID 列が存在し、どの PDB かを識別することができます。PDB の状態が OPEN 状態の場合のみ出力されます（後述）。

```SQL: データファイルのリスト
SQL> SELECT TABLESPACE_NAME, FILE_NAME FROM CDB_DATA_FILES WHERE CON_ID=4;

TABLESPACE_NAME                FILE_NAME
------------------------------ --------------------------------------------------------------------------------
SYSTEM                         +DATA1/O19C/9EFAF87C09DA3F6FE0559213D55B30AE/DATAFILE/system.324.1032822137
SYSAUX                         +DATA1/O19C/9EFAF87C09DA3F6FE0559213D55B30AE/DATAFILE/sysaux.323.1032822137
UNDOTBS1                       +DATA1/O19C/9EFAF87C09DA3F6FE0559213D55B30AE/DATAFILE/undotbs1.325.1032822137

SQL> SELECT TABLESPACE_NAME, FILE_NAME FROM CDB_TEMP_FILES WHERE CON_ID=4;

TABLESPACE_NAME                FILE_NAME
------------------------------ --------------------------------------------------------------------------------
TEMP                           +DATA1/O19C/9EFAF87C09DA3F6FE0559213D55B30AE/TEMPFILE/temp.322.1032822141
```

ファイル名のパスにはV$PDBSビューのGUIDが付与されています。これはPDB作成時にFILE_NAME_CONVERTを指定しなかった場合です。


# PDBの状態
作成した直後の PDB は MOUNTED 状態で、管理者以外は接続できません。一般ユーザーに接続を許可するには PDB を OPEN 状態に移行する必要があります。ALTER PLUGGABLE DATABASE 文を実行します。下記の例では PDB3 を OPEN 状態に移行しています。V\$PDBSビューの OPEN_MODE 列が READ WRITE に変化しています。

```SQL: PDB の状態
SQL> SELECT CON_ID, NAME, OPEN_MODE FROM V$PDBS;

    CON_ID NAME                           OPEN_MODE
---------- ------------------------------ ----------
         2 PDB$SEED                       READ ONLY
         3 PDB1                           MOUNTED
         4 PDB3                           MOUNTED
         5 PDB2                           MOUNTED

SQL> ALTER PLUGGABLE DATABASE pdb3 OPEN;

プラガブル・データベースが変更されました。

SQL> SELECT CON_ID, NAME, OPEN_MODE FROM V$PDBS;

    CON_ID NAME                           OPEN_MODE
---------- ------------------------------ ----------
         2 PDB$SEED                       READ ONLY
         3 PDB1                           MOUNTED
         4 PDB3                           READ WRITE
         5 PDB2                           MOUNTED
```

インスタンスが再起動すると、PDBの状態はMOUNTED状態に戻ります。インスタンス起動時に停止時の状態を維持するには、ALTER PLUGGABLE DATABASE SAVE STATE文を実行します。元に戻す場合はALTER PLUGGABLE DATABASE DISCARD STATE文を実行します。

```SQL: 再起動時のじょうたい
SQL> ALTER PLUGGABLE DATABASE pdb3 SAVE STATE;

プラガブル・データベースが変更されました。

SQL> SELECT CON_NAME, STATE FROM DBA_PDB_SAVED_STATES;

CON_NAME                       STATE
------------------------------ --------------
PDB3                           OPEN

SQL> ALTER PLUGGABLE DATABASE pdb3 DISCARD STATE;

プラガブル・データベースが変更されました。

SQL> SELECT CON_NAME, STATE FROM DBA_PDB_SAVED_STATES;

レコードが選択されませんでした。

```