🎃

Oracle Databaseマルチテナント構成 (CDB/PDB)

2023/10/13に公開

概要

複数のデータベースを1つのインスタンスに統合できる技術のことデータベース層でマルチテナントを実現できる技術のこと。コンテナ・データベース(CDB)と呼ばれる器の中に、プラガブル・データベース(PDB)を最大252個作成でき(ライセンスやエディション依存)、インスタンスやバックグラウンド・プロセスを共有することで集約率を大幅に高めることが可能。

CPU/メモリなどのリソース使用量を削減できることに加え、今までデータベースごとに行っていた起動・停止、バックアップ、パッチの適用を一括で行うことも可能。ランニングコスト/運用コスト的なメリットがある。

またアプリケーションから見ると従来の非CDBと同じように見えるので、スキーマやテーブルで分割していた設計をデータベース単位での手軽な分割を容易にできる。例えばスキーマ分割だと権限さえつけてしまえば、ほかのスキーマのデータを参照・更新もできてしまうので、完全に分離できるかと言われると怪しい部分があったが、データベース (PDB) で分ければ完全な分離を実現可能である。

なお、Oracle Database 21c からは従来型の非 CDB 構成は利用できないのでこの CDB 構成が必須。

CDB内の構成

  • CDB$ROOT(ルート)

    • CDBの基盤となるコンテナ。CDB内の全コンテナで共有するオブジェクトやメタデータが格納される。
    • オブジェクトの追加や削除はできない。CDBに対してローカル接続するとこれに接続される。
  • PDB$SEED(シード)

    • PDBを新規に作成するときのひな形(テンプレート)。CDB作成時に、1つだけ作成される。
    • 読み取り専用で、オブジェクトの追加や変更はできません
  • PDB(プラガブル・データベース)

    • マルチテナント・アーキテクチャに統合するデータベースに相当。
    • PDBごとにスキーマや表領域の独立した名前空間を持ち、同一のCDB内の複数のPDBで同じ名称のスキーマや表領域を使用可能。
    • 1つのCDBに対して、最大252個のPDBを作成可能。(Enterprise Editionは)
    • CDBからPDBを取り外したり(Unplug)、取り外したPDBを別のCDBまたは以前と同じCDBに取り付ける(Plug)ことができる

CDBとPDBで共有されるもの/共有されないもの

<strong>共有される部分</strong>

  • インスタンスが提供するメモリやバックグラウンドプロセスなどのリソース
  • オンラインREDOログやUNDO表領域(ローカルUNDOモードであればUNDO表領域は共有されない)
  • 共通ユーザ。CDB$ROOTとCDB内の全PDBで共通に使用されるユーザー。
    • デフォルトでSYS、SYSTEMユーザーが共通ユーザー。で個別に作成する場合は接頭辞(C##、c##)をつけてユーザーを作る。
    • 共通ユーザはCDB、全PDBに作成されるが権限は各DBで付与されている状態で個別となる。
  • RDBMSのアラートログ。CDBと全PDBで共通。

<strong>共有されない部分</strong>

  • SYSTEM表領域・SYSAUX表領域・TEMP表領域。その他永続表領域。
  • PDBの表領域にはあくまでPDB固有のデータのみ入る。コンテナデータベース全体のデータとしてはCDB$ROOTに格納される
  • ローカルユーザ。特定のPDBにのみに存在するユーザー。アプリケーション固有のユーザーは一般にローカル・ユーザーとする。

PDB のプロビジョニング方法

シードPDBから作成

alter pluggable database pdb1 close immediate;
drop PLUGGABLE DATABASE pdb1 including datafiles;
CREATE PLUGGABLE DATABASE pdb1 ADMIN USER admin IDENTIFIED BY P#ssw0rd ROLES=(DBA) STORAGE (MAXSIZE 10G);
alter pluggable database pdb1 open;
ALTER PLUGGABLE DATABASE pdb1 SAVE STATE;
alter session set container=pdb1;
show con_name;

別の PDB から PDB をクローニング

alter pluggable database pdb1 close immediate;
alter pluggable database pdb1 open read only;
alter pluggable database pdb2 close immediate;
drop PLUGGABLE DATABASE pdb2 including datafiles;
CREATE PLUGGABLE DATABASE pdb2 from pdb1;
alter pluggable database pdb2 open;
ALTER PLUGGABLE DATABASE pdb2 SAVE STATE;
alter session set container=pdb2;
show con_name;
  • ソースでアーカイブモードが有効、かつ、ローカルUNDOモードが有効であれば、クローニング元のpdbはread writeでも良い。そうではない場合は read only でオープンしておく必要あり。
  • データベースリンクでリモートからクローニングすることも可能。
    • CREATE PLUGGABLE DATABASE pdb2 from pdb1@<データベースリンク名>;

留意点

  • 作成後は対象の pdb は MOUNT。
  • 作成するPDBの配置場所の優先順位
    1. 作成ステートメント内の FILE_NAME_CONVERT 句で指定した場所
    2. 作成ステートメント内の CREATE_FILE_DEST 句で指定した場所
    3. 初期パラの db_create_file_dest で指定した場所
    4. 初期パラの pdb_file_name_convert で指定した場所
  • <strong>roles</strong>
    • 作成するローカル管理者ユーザーに付与するロール
    • なお、作成したローカル管理者ユーザーにはPDB_DBAというからロールが付与される
  • <strong>storage</strong>
    • PDB に属する表領域の最大サイズ
  • <strong>max_shared_temp_size</strong>
    • 共有一時表領域の使用サイズ制限

CDB/PDBへの接続

  • CDB への接続
    • ローカル接続/リモート接続いずれも可能
    • ローカル接続の場合は ORACLE_SID 環境変数をCDB名にして通常通り接続
    • リモート接続の場合、[CDB名].[CDB の初期パラ db_domain] というサービス名
  • PDB への接続
    • 直接接続できるのはリスナー経由のリモート接続のみ可能。
    • サービス名は、[PDB名].[CDB の初期パラ db_domain]
    • pdb作成後にリスナーにサービス名が動的登録される。
    • CDB (CDB$ROOT) 経由で set container 文で接続することもできるが、この場合同一ユーザー名で切り替わるので前提として、sys や system、その他共通ユーザーを使う必要がある点に注意。
      • set container 権限が付与された共通ユーザーであればopenしているpdbに接続可能。
      • sysdba の場合はopenしていないpdbへの接続も加えて可能。
      • set container 文で切り替えた場合、alter login トリガーは発動しない。
    • pdb間で通信する場合は、通常リモートのDBと通信する場合に使うようにデータベースリンクを使う。
    • デフォルトの[PDB名].[CDB の初期パラ db_domain]以外のサービス名を特定のpdbで追加したい場合は、DBMS_SERVICE パッケージを使って追加サービス名を定義する。例としては以下でこの後リスナーにサービス名が追加されることが期待される。
DBMS_SERVICEパッケージによるpdbサービス名追加
-- 管理名,ネットワーク名
exec DBMS_SERVICE.CREATE_SERVICE('pdb2_sales','sales');

-- サービス開始
exec DBMS_SERVICE.START_SERVICE('pdb2_sales');

PDB起動モード

CDB/PDB間の起動モードの関連性

  • <strong>CDB が CLOSE/NOMOUNT の場合</strong>
    • PDB は一切起動不可。
  • <strong>CDBが MOUNT の場合</strong>
    • PDB は MOUNT モードでの起動のみ可能。
    • PDB が MOUNT 状態でも sysdba 権限でサービス名経由で接続可能。(connect sys@pdbx as sysdba)
  • <strong>CDB が OPEN の場合</strong>
    • CDB が OPEN READ WRITE の場合
      • PDB は MOUNT/OPEN READ WRITE/OPEN READ ONLY/OPEN RESTRICTED モードでの起動が可能
    • CDB が OPEN READ ONLY の場合
      • PDB は MOUNT/OPEN READ ONLY モードでの起動が可能
    • CDB が OPEN RESTRICTED の場合
      • PDB は MOUNT/OPEN RESTRICTED モードでの起動が可能

PDB の初期化パラメータ

  • PDB には SPFILE は存在せず、初期パラはデータディクショナリ <strong>PDB_SPFILE$</strong> で管理される
  • 初期化パラメータにはPDBで個別変更できるものも出来ないものもある。PDB で個別変更できる初期パラは以下で確認可能。
  • ISPDB_MODIFIABLE = false のパラメータは常に CDB で変更する必要がある。CDB で変更すれば PDB へはそのまま継承される。PDB で変更しようとすると、ORA-65040: operation not allowed from within a pluggable database
  • ISPDB_MODIFIABLE = true のパラメータは PDB で個別変更可能。特に PDB で個別変更されていなければ、CDB$ROOT の値を継承。
  • https://docs.oracle.com/cd/F19136_01/sqlrf/ALTER-SYSTEM.html#GUID-2C638517-D73A-41CA-9D8E-A62D1A0B7ADB
col name format a50
col value format a50
select name,value,ISDEFAULT,ISSES_MODIFIABLE,ISSYS_MODIFIABLE,ISPDB_MODIFIABLE from V$SYSTEM_PARAMETER order by 1;

CDB レベルでのみ構成できる項目

基本的に PDB 単位でできる設定項目は多いが以下の項目は CDB レベルで実施する必要がある。

  • 制御ファイルの構成
  • REDOログファイルの構成
  • UNDO 表領域構成
  • リカバリ関連項目の構成
    • アーカイブログモード
    • フラッシュバックデータベース
    • 変更追跡ファイル など

ローカルUNDOモード

Oracle12cR2以降ではローカルUNDOモードと言って、全てのコンテナで個別のUNDO表領域を持つように構成することができる。
あくまで、すべてのコンテナでローカルUNDOを使用するか、CDB全体で共有UNDOを使用するかの2択でCDBを構成。

UNDOモード確認
col PROPERTY_NAME format a30
col PROPERTY_VALUE format a30
SELECT PROPERTY_NAME, PROPERTY_VALUE FROM   DATABASE_PROPERTIES
WHERE  PROPERTY_NAME = 'LOCAL_UNDO_ENABLED';
  • ローカルUNDOモードへ変更する場合、CDBを UPGRADE モードで起動する必要あり
  • ローカルUNDOモードへ変更後、PDBを起動すると自動的にPDB内でUNDO表領域が生成されていることがわかる
ローカルUNDOモード変更
shutdown immediate;
startup upgrade;
ALTER DATABASE LOCAL UNDO ON;
shutdown immediate;
startup;

共通ユーザー/ローカルユーザー作成

CDB 構成では、全コンテナで共通作成される共通ユーザー、各PDBでのみ利用できるローカルユーザーという概念がある。

  • <strong>ローカルユーザー</strong>
    • 各コンテナでのみ利用できるユーザーのこと。
    • ローカルユーザーは PDB でのみ作成可能。
  • <strong>共通ユーザー</strong>
    • 全コンテナで共通的に作成されるユーザーで、デフォルトでは接頭辞が C##。
    • 共通ユーザーは CDB でのみ作成可能。CDB で作成すると全コンテナにも作成される
    • CDBでcreate user権限とset container権限を持つ共通ユーザーで作成する
    • デフォルト表領域や一時表領域を指定する場合 read write でオープンしているコンテナに対象表領域が存在している必要性がある。read writeでオープンしていないPDBでは次回read writeでオープンした時に共通ユーザーの作成が行われる。
    • 接頭辞は、common_user_prefix パラメータで定義される
共通ユーザー作成
create user C##ADMIN identified by "P#ssw0rd";
全コンテナ分のユーザーをCDBで確認
select con_id,username,common from cdb_users;

共通ロール/ローカルロール作成

  • ユーザー同様に、共通ロール、ローカルロールという概念があり、共通ロールはCDBで、ローカルロールはPDBでのみ作成可能

マルチテナント環境での権限付与

マルチテナント環境では権限付与の方式として、共通的に付与する場合、ローカルで付与する場合の2通りがある。

  • 権限の共通付与

    • 全コンテナに対して特定の権限を付与する。grant 文にcontainer=ALLを付与して実行
    • CDB でのみ権限付与は実行可能。
    • 権限を共通に付与できるのは共通ユーザーのみ、権限受領者は共通ユーザーや共通ロールである必要あり。
    • 付与する対象の権限は共通ロールでも良いし、その他システム権限やオブジェクト権限でも良い。
  • 権限のローカル付与

    • ローカルに付与された権限は、それが付与されたコンテナでのみ使用。grant文にcontainer=current(デフォルト)を付与して実行
    • CDB/PDBいずれでも実行できる。
  • 共通ユーザーによる特定のPDBへのアクセス許可

    • データディクショナリや動的パフォーマンスビューについてデフォルトだと sys,system 等一部のデフォルトの共通ユーザー以外はローカルコンテナの情報にのみアクセス可能。
    • 他の共通ユーザーについて、CDB上で任意のPDBの情報をみたい場合は権限を付与することで可能。
共通ユーザーによる特定のPDBへのアクセス許可
CREATE USER c##my_user IDENTIFIED BY MyPassword1;
GRANT CREATE SESSION, DBA TO c##my_user CONTAINER=ALL;

ALTER USER c##my_user ADD CONTAINER_DATA=(PDB1) CONTAINER=current;

col USERNAME format a30
col OBJECT_NAME format a30
col CONTAINER_NAME format a30
select username,default_attr,object_name,all_containers,container_name from cdb_container_data;

USERNAME		      |D|OBJECT_NAME		       |A|CONTAINER_NAME
------------------------------|-|------------------------------|-|------------------------------
---
C##MY_USER		      |Y|			       |N|PDB1
---

PDB ロックダウンプロファイル

PDB Lockdown Profilesは、共有されたコンテナ環境でデータベースを使用しながらもセキュリティを必要とする場合に、アクセスの制限や有効化を細かく制御する方法。grant で権限付与している上にさらに細かい制限を埋め込むといった類のもの。例として、ALTER SYSTEMを実行しているときに、特定のPDBにログインしたユーザーのみに対し特定の初期パラメータを変更できるように許可することができる。(他にも有償オプション等も制限できる) CDB側で上から制御するので、PDB 側から解除はできない。

  • CDB でロックダウンプロファイルを有効化・設定して PDB_LOCKDOWN パラメータに設定
create lockdown profile PL;
alter lockdown profile PL 
disable statement=('ALTER SYSTEM') clause=('SET') OPTION ALL EXCEPT=('open_cursors');
alter system set PDB_LOCKDOWN=PL;
  • 特定のPDBに接続して上記で許可された open_cursors 以外のパラメータを alter system で変更しようとすると権限エラーとなり、PDB に対して制限がかかっていることがわかる
SQL> alter system set sga_target=600M;
alter system set sga_target=600M
*
ERROR at line 1:
ORA-01031: insufficient privileges
  • PDB ロックダウンプロファイルの設定状況をCDBから確認
col profile_name format a30
col rule_type format a30
col rule format a30
col clause format a30
col clause_option format a30
col status format a20
select profile_name, rule_type, rule, clause, clause_option, status from DBA_LOCKDOWN_PROFILES order by 1;

SQL> 
PROFILE_NAME		      |RULE_TYPE		     |RULE			    |CLAUSE			   |CLAUSE_OPTION		  |STATUS
------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|--------------------
PL			      |STATEMENT		     |ALTER SYSTEM		    |SET			   |				  |DISABLE
PL			      |STATEMENT		     |ALTER SYSTEM		    |SET			   |OPEN_CURSORS		  |ENABLE
PRIVATE_DBAAS		      | 			     |				    |				   |				  |EMPTY
PUBLIC_DBAAS		      | 			     |				    |				   |				  |EMPTY
SAAS			      | 			     |				    |				   |				  |EMPTY

アプリケーションコンテナ

Multitenant : Application Containers in Oracle Database 12c Release 2 (12.2)
Application containers are a new feature in Oracle Database 12c Release 2 (12.2) that allow you to define an application root, like a mini CDB root container, along with dependent application container PDBs. An application root can house one or more applications, each made up of shared configuration, metadata and objects that are used by the pluggable databases associated with the application root.

(参考)https://oracle-base.com/articles/12c/multitenant-application-containers-12cr2

マルチテナント環境でのリソース・マネージャー

CDB 環境でも非CDB環境同様にリソースの使用量をリソースマネージャーによって制御することが出来る。
リソースマネージャーで各PDBのCPU使用率やパラレルサーバープロセス数を制限することができる。

PDB ディレクティブに指定できる値として以下。

  • share
    • PDBに割り当てるリソース使用量の最低保証値を比率で指定する。例えば、PDB1が1でPDB2が2であればPDB2の方が最低保証値はPDB1の2倍。
    • デフォルト値は1
  • utilization_limit
    • CPU使用率の最大値を0%-100%の間で指定する。
    • そのCDBで利用可能なCPU数(デフォルトだと無制限)を100%として割合を指定する。例えばインスタンスケージングをCDBで適用していてcpu_count=1であればその1vCPUの中でそのPDBが使える最大CPU使用率を定義することになる。
  • parallel_server_limit
    • パラレルサーバープロセス数の最大値を0%-100%の間で指定する。
    • そのCDBで割り当てられたPARALLEL_SERVERS_TARGETに対する割合。
リソース・マネージャーをCDBで設定する
-- 1.PENDING AREA 作成
exec DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA()

-- 2.CDB PLAN 作成
exec DBMS_RESOURCE_MANAGER.DELETE_CDB_PLAN(plan=>'PLANA');
exec DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN(plan=>'PLANA',comment=>'testing plan')

-- 3.PDB DIRECTIVE 設定
exec DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE('PLANA','PDB1',shares=>1,utilization_limit=>20,parallel_server_limit=>30);
exec DBMS_RESOURCE_MANAGER.CREATE_CDB_PLAN_DIRECTIVE('PLANA','PDB2',shares=>4,utilization_limit=>70,parallel_server_limit=>30);

-- 4.PENDING AREA 検証
exec DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA()

-- 5.PENDING AREA 確定
exec DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA()

-- CDB PLAN & PDB DIRECTIVE 確認
col PLAN format a30
col PLUGGABLE_DATABASE format a30
SELECT plan,
       pluggable_database,
       shares,
       utilization_limit AS util,
       parallel_server_limit AS parallel
FROM   dba_cdb_rsrc_plan_directives
WHERE  plan = 'PLANA'
ORDER BY plan, pluggable_database, profile;

PLAN			      |PLUGGABLE_DATABASE	     |	  SHARES|      UTIL|  PARALLEL
------------------------------|------------------------------|----------|----------|----------
PLANA			      |ORA$AUTOTASK		     |		|	 90|
PLANA			      |ORA$DEFAULT_PDB_DIRECTIVE     |	       1|	   |
PLANA			      |PDB1			     |	       1|	 20|	    30
PLANA			      |PDB2			     |	       4|	 70|	    30

-- 作成したプランを利用するように切り替え
exec DBMS_RESOURCE_MANAGER.SWITCH_PLAN ('PLANA');
show parameter resource_manager_plan

NAME				    |TYPE	|VALUE
------------------------------------|-----------|------------------------------
resource_manager_plan		    |string	|PLANA

-- それぞれのPDBCPUを消費する以下のPL/SQLを実行すればCPU使用率がそれぞれのサーバープロセスで制限されていることが分かる
exec BEGIN while ( true ) loop NULL; end loop; END;

-- 以下クエリでそれぞれのPDBでのCPU使用率(OS上の全vCPUを基準とした割合)を確認可能
col PDB_NAME format a30
SELECT r.BEGIN_TIME, r.END_TIME,r.CON_ID, p.PDB_NAME, r.CPU_UTILIZATION_LIMIT, r.AVG_CPU_UTILIZATION
FROM V$RSRCPDBMETRIC_HISTORY r, CDB_PDBS p
WHERE r.CON_ID = p.CON_ID AND p.PDB_NAME in ('PDB1','PDB2')
ORDER BY PDB_NAME,BEGIN_TIME;

CDB 構成時のフラッシュバックデータベース

https://www.oracle.com/jp/technical-resources/articles/database/cosol-db12cr2/cosol-4.html

SQL 文での CDB 作成

https://docs.oracle.com/cd/F32587_01/multi/creating-and-configuring-an-oracle-database.html#GUID-F90F2625-60F1-4C26-81D0-E91CAF540B22

export ORACLE_SID=CDB 
mkdir -p /rdsdbdata/db
rm -rf /rdsdbdata/db/CDB

cat << EOF > initCDB.ora 
db_name=CDB
db_create_file_dest='/rdsdbdata/db'
enable_pluggable_database=true
EOF

sqlplus -S / as sysdba << EOF 
shutdown abort;
startup nomount pfile='initCDB.ora'
EOF

sqlplus -S / as sysdba << EOF 
CREATE DATABASE CDB 
USER SYS IDENTIFIED BY P#ssw0rd
USER SYSTEM IDENTIFIED BY P#ssw0rd
SET DEFAULT BIGFILE TABLESPACE
CHARACTER SET AL32UTF8
NATIONAL CHARACTER SET AL16UTF16
EXTENT MANAGEMENT LOCAL
ARCHIVELOG
DATAFILE SIZE 125M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
SYSAUX DATAFILE SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
DEFAULT TABLESPACE USERS DATAFILE SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
UNDO TABLESPACE UNDO_T1 DATAFILE SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
ENABLE PLUGGABLE DATABASE
   SEED
   SYSTEM DATAFILES SIZE 125M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
   SYSAUX DATAFILES SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
;
EOF

@?/rdbms/admin/catcdb.sql /tmp create_cdb.log
create spfile='?/dbs/spfileCDB.ora' from memory;

その他

https://oracle-base.com/articles/12c/multitenant-configure-instance-parameters-of-cdb-and-pdb-12cr1
https://www.oracle.com/technetwork/jp/database/articles/cosol-db12cr2/cosol-3-3849601-ja.html

Discussion