はじめに
実機環境には Oracle AI Database 26ai Free(CDB=FREE / PDB=FREEPDB1)を使います。Vagrant + VirtualBox での構築手順は以下にまとめています。
- 実機環境: Oracle AI Database 26ai Free(CDB=
FREE/ PDB=FREEPDB1)。Vagrant + VirtualBox で構築しています。 - 環境構築がまだの方はこちらからどうぞ → Oracle AI Database 26ai Free を自分のPCに入れる(Vagrant版)
- 前前々回 #1-1「RDB・SQL・重要用語」はこちら → 実際に触って学ぶBronze DBA(26ai)#1-1
- 前々回 #1-2「インスタンスとデータベースのコンポーネント」はこちら → 実際に触って学ぶBronze DBA(26ai)#1-2
- 前回 #1-3「データベース・ファイルの理解」はこちら → 実際に触って学ぶBronze DBA(26ai)#1-3
免責
この連載「実際に触って学ぶBronze DBA(26ai)」は、ORACLE MASTER Bronze DBA(Oracle AI Database 26ai / 1Z0-185-JPN)の試験範囲を題材に、実際に手を動かしながら理解を深めることを目的としています。
本連載は合格保証や試験対策そのものを目的とするものではありません。試験範囲を使い、その一つひとつを実機で確かめていく知識補完の記事、という位置づけです。
今回記事の範囲
第1章:Oracleデータベース管理の概要
- リレーショナル・データベースおよびSQLの理解 … #1-1(済)
- インスタンスおよびデータベースのコンポーネントの理解 … #1-2(済)
- ✅ マルチテナント・コンテナ・データベースの利点の理解 … 今回
- データベース・ファイルの理解 … #1-3(済)
- Oracleデータベースの管理に使用するツールの理解 … #1-1(済)
- Oracleデータベースの重要な用語の理解 … #1-1(済)
- Oracle AI Database 26aiの新機能の概要 … #1-5で解説予定
- Oracle AI Database 26aiの特徴と利点 … #1-5で解説予定
前回(#1-3)の振り返り
前回の #1-3「データベースを構成するファイル」 では、データベースを構成する物理ファイルを実機で一通り眺めました。
- データファイルは
CON_IDごとに分かれていて、PDB はそれぞれ自分専用のSYSTEM表領域を持っている - 一方で制御ファイルとREDOログはCDB全体で1セットしかない
「なぜ分かれているものと共有されているものがあるのか」「その分け方で結局何が嬉しいのか」。今回はそこに踏み込みます。
そして今回は、この連載で初めて構成を変更する操作をします。
PDBを自分の手で1つ作ってみます。もちろん、作りっぱなしにはせず、最後にきちんと片付けるところまでやります。
マルチテナント以前
マルチテナントの利点を理解するには、まず「それがなかった頃は何が困っていたのか」から入るのがいちばんの近道です。
#1-2 で、インスタンス=エンジン、データベース=燃料タンクというたとえを使いました。エンジン(メモリ上の作業場とバックグラウンド・プロセス群)が動いて、燃料タンク(ディスク上のファイル)からデータを出し入れする、という関係です。
マルチテナント以前は、この組み合わせが原則として1対1でした。データベースが1つあれば、それ専用のインスタンスが1つ必要です。
ここで、業務システムを3つ運用することになったとします。人事システム、販売管理システム、在庫管理システム。それぞれデータは独立させたいので、データベースを3つ作ります。すると、こうなります。
| 非CDB構成 | |
|---|---|
| データベース | 3つ |
| インスタンス | 3つ |
| SGA(メモリ) | 3つ分 |
| バックグラウンド・プロセス | 3セット |
| データ・ディクショナリ | 3つ分(中身はほぼ同じ) |
| バックアップ設定 | 3つ分 |
| パッチ適用 | 3回 |
データベースの数に比例して、すべてが増えていきます。
たとえるなら、一戸建てを3軒建てるようなものです。3世帯が住むために、玄関も屋根も水道管も電気の引き込みも、全部3セット必要になります。
さらに、実際の運用では各データベースの負荷が同時にピークを迎えることは稀です。人事システムが忙しいのは月末、販売管理が忙しいのは日中。それでもメモリは3つ分を常に確保しておく必要があります。
そして管理コスト。パッチを当てるときは3回、バージョンアップも3回、バックアップの設定も3つ分。データベースが30個あったら、この作業はそのまま30倍になります。
この「一戸建てを何軒も建てる」やり方をやめて、1棟のマンションを建てて部屋を分けることにしたのが、Oracle Database 12c で導入されたマルチテナント・アーキテクチャです。
Oracle の公式ドキュメント『概要』には、Oracle Database 21c 以降、マルチテナント・コンテナ・データベースがサポート対象の唯一のアーキテクチャであると明記されています。
CDBとPDB
用語を整理します。
-
CDB(マルチテナント・コンテナ・データベース)=マンションの建物全体
この環境ではFREEがそれにあたります。基礎・外壁・水道管・電気の引き込みといった「建物としての設備」を持っています。 -
PDB(プラガブル・データベース)=部屋
この環境ではFREEPDB1です。住人(アプリケーション)から見れば、ここが「自分のデータベース」です。 -
CDB$ROOT=共用部
エントランス、管理人室、配電盤。全部屋が共通で使う設備と、建物全体の管理情報がここにあります。 -
PDB$SEED=モデルルーム
新しい部屋を作るときの「ひな型」です。家具の配置も内装も決まった状態で用意されていて、中身は書き換えられません(読み取り専用)。
大事なのは、アプリケーションから見た PDB は普通のデータベースと変わらないという点です。部屋に住んでいる人は、自分の部屋のことだけ知っていれば生活できます。「この建物には他に何部屋あるのか」「配電盤はどこか」を意識する必要はありません。
【ラボ0】いま自分はどこにいるのか
さっそく実機で確認します。以下は CDB ルート(CDB$ROOT)に SYSDBA で接続して実行します。
$ vagrant ssh
$ sudo su - oracle
$ sqlplus / as sysdba
出力が読みやすくなるよう、最初に表示幅を整えておきます。この連載では以降もこの設定を前提にします。
SET LINESIZE 200
SET PAGESIZE 100
COLUMN name FORMAT A50
COLUMN pdb_name FORMAT A20
COLUMN open_mode FORMAT A12
COLUMN username FORMAT A20
まず、自分がいまどのコンテナにいるかを確認します。
SHOW CON_NAME
SHOW CON_ID
CON_NAME
------------------------------
CDB$ROOT
CON_ID
------------------------------
1
CDB$ROOT の CON_ID は必ず 1 です。マンションでいえば、いま管理人室に立っている状態です。
次に、この建物にどんな部屋があるかを見ます。
SELECT con_id, name, open_mode FROM v$containers ORDER BY con_id;
CON_ID NAME OPEN_MODE
---------- -------------------------------------------------- ------------
1 CDB$ROOT READ WRITE
2 PDB$SEED READ ONLY
3 FREEPDB1 READ WRITE
3つ表示されました。PDB$SEED が READ ONLY になっているところに注目してください。モデルルームは眺めるためのもので、勝手に模様替えはできません。
同じような情報を別のビューでも見てみます。
SELECT pdb_id, pdb_name, status FROM cdb_pdbs ORDER BY pdb_id;
PDB_ID PDB_NAME STATUS
---------- -------------------- ----------
2 PDB$SEED NORMAL
3 FREEPDB1 NORMAL
CDB$ROOT が消えました。 これは間違いではありません。V$CONTAINERS は「コンテナの一覧」なので共用部も含みますが、CDB_PDBS は「PDB の一覧」なので、PDB ではない CDB$ROOT は対象外なのです。
ルートはコンテナだが、PDB ではない。 マンションでいえば、共用部は建物の一部ですが「部屋」ではない、ということです。
共有するもの、分けるもの
マルチテナントの設計思想は、ひとことで言えば 「共有できるものは共有し、分けるべきものは分ける」 です。この線引きが、そのまま利点に直結します。
| 所有者 | マンションでいうと | |
|---|---|---|
| インスタンス(SGA・プロセス) | CDB で共有 | 建物の受電設備・給水ポンプ |
| 制御ファイル | CDB で1セット | 建物全体の管理台帳 |
| REDO ログ | CDB で1セット | 建物全体の作業日誌 |
| データファイル | PDB ごと | 各部屋の家財道具 |
| UNDO 表領域 | PDB ごと(ローカルUNDO) | 各部屋のゴミ箱 |
| 一時ファイル | PDB ごと(+CDB共通) | 各部屋の作業机 |
| データ・ディクショナリ | ルートに実体、PDB にはリンク | 共用部の設備台帳を各部屋から参照 |
最後の行が、マルチテナントのいちばん賢いところです。
Oracle が提供する膨大なシステム定義(PL/SQL パッケージのソース、システム表の定義など)は、実体を CDB$ROOT に1つだけ持ちます。各 PDB は自分の SYSTEM 表領域に「その実体を指すリンク」だけを持ち、実データは持ちません。だから PDB を1つ増やしても、Oracle 標準部分がまるごとコピーされることはないのです。
一方で、各 PDB が自分で作った表やユーザーの定義は、その PDB の SYSTEM 表領域に格納されます。共通部分は共有し、固有部分だけ持つ。 これが「非CDB を3つ並べる」より効率的な理由です。
マンションでいえば、水道の本管や受電設備は建物に1セットあれば十分で、各部屋が個別に井戸を掘る必要はありません。でも、部屋の中の家具は住人ごとに違います。
共有と分割を実機で確認する
まずインスタンスの数を数えます。
SELECT instance_name, status FROM v$instance;
INSTANCE_NAME STATUS
---------------- ------------
FREE OPEN
1行だけです。 PDB がいくつあろうと、インスタンスは1つ。
続いて制御ファイルと REDO ログ。#1-3 で見たものの再確認です。
SELECT name FROM v$controlfile;
NAME
--------------------------------------------------
/opt/oracle/oradata/FREE/control01.ctl
/opt/oracle/oradata/FREE/control02.ctl
SELECT group#, member FROM v$logfile ORDER BY group#;
GROUP# MEMBER
---------- --------------------------------------------------
1 /opt/oracle/oradata/FREE/redo01.log
2 /opt/oracle/oradata/FREE/redo02.log
3 /opt/oracle/oradata/FREE/redo03.log
パスに FREEPDB1 が出てきません。これらは建物全体のものだからです。
対してデータファイルは、CON_ID ごとに分かれています。
SELECT con_id, COUNT(*) AS files FROM v$datafile GROUP BY con_id ORDER BY con_id;
CON_ID FILES
---------- ----------
1 3
2 3
3 3
ここで PDB$SEED(CON_ID = 2)にもデータファイルが3つある点に注目してください。#1-3 で確認したとおり、その内訳は system01.dbf / sysaux01.dbf / undotbs01.dbf です。
モデルルームが UNDO 表領域を持っている、つまり PDB は自分専用の UNDO を持つ設計になっている、ということです。これをローカルUNDOモードと呼びます。実際に確認できます。
SELECT property_name, property_value
FROM database_properties
WHERE property_name = 'LOCAL_UNDO_ENABLED';
PROPERTY_NAME PROPERTY_VALUE
------------------------------ --------------------
LOCAL_UNDO_ENABLED TRUE
UNDO が PDB ごとに分かれていることには意味があります。部屋ごとにゴミ箱があるから、部屋を丸ごと別の建物に引っ越させることができるのです。これは後述の利点③の伏線になっています。
利点①
ここからは利点を4つ順番に見ていきます。
さきほど V$INSTANCE が1行しか返さなかったことを思い出してください。仮にこの CDB に PDB が10個あったとしても、結果は変わりません。
- SGA は1つ
- バックグラウンド・プロセス(
PMON、SMON、DBWn、LGWRなど)は1セット - リスナーへの登録も1つのインスタンス配下
非CDB を10個並べたら、SGA が10個、プロセスが10セット必要でした。マルチテナントなら1セットを10部屋で分け合えます。
これは単に「メモリが節約できる」という話にとどまりません。前述したとおり、各システムのピーク時間帯はバラバラです。1つの大きなメモリ領域を共有していれば、忙しい部屋が空いているリソースを使えるわけです。
その代わりのトレードオフもあります。インスタンスは共有されているので、CDB を停止すればすべてのPDBが止まります。 部屋ごとに開け閉めはできますが、建物の受電設備を落とせば全部屋が停電します。「集約する」とは、そういう運命共同体になることでもあります。
なお、この環境は Free 版です。公式のライセンス制限として、CPU は2コアまで、RAMは2GBまで、ユーザー・データは12GBまでと定められています。ラボ用途では十分ですが、大量のPDBを作って性能を測るような使い方には向かない点は頭の片隅に置いておいてください。
利点②
部屋はすぐ増やせる
非CDB の時代、新しいデータベースを1つ作るのは大仕事でした。DBCA を起動して、初期化パラメータを決めて、データ・ディクショナリを作成して……。環境にもよりますが、数十分から数時間かかる作業です。一戸建てを新築するわけですから、当然です。
マルチテナントでは違います。モデルルーム(PDB$SEED)をコピーするだけです。内装も設備も完成済みのものを複製するので、あっという間に終わります。
実際にやってみましょう。
ラボを始める前に
ここからはデータベースの構成を変更する操作です。この連載で初めてになります。以下を確認してから進めてください。
- 実行場所は CDB ルート(
CDB$ROOT)にSYSDBAで接続した SQL*Plus - 検証用の環境で実施すること(業務環境では絶対にやらないでください)
- 記事の最後に片付け手順があります。必ず最後まで実施してください
まず、この環境がファイルをどこに置くかを確認します。
SHOW PARAMETER db_create_file_dest
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_create_file_dest string
値が空です。 このパラメータは「データファイルの置き場所を Oracle に任せる」設定(Oracle Managed Files、OMF)で、値が入っていれば Oracle が自動でパスを決めてくれます。空ということは、ファイルの置き場所を自分で指定する必要があるということです。
ここを確認せずに PDB を作ろうとすると ORA-65005 で失敗します。今回は FILE_NAME_CONVERT 句で置き場所を明示する方法をとります。OMF そのものの詳細は上位資格の範囲なので、ここでは深追いしません。
コピー元となる PDB$SEED のファイルの場所を確認します。
SELECT con_id, name FROM v$datafile WHERE con_id = 2;
SELECT con_id, name FROM v$tempfile WHERE con_id = 2;
CON_ID NAME
---------- --------------------------------------------------
2 /opt/oracle/oradata/FREE/pdbseed/system01.dbf
2 /opt/oracle/oradata/FREE/pdbseed/sysaux01.dbf
2 /opt/oracle/oradata/FREE/pdbseed/undotbs01.dbf
CON_ID NAME
---------- --------------------------------------------------
2 /opt/oracle/oradata/FREE/pdbseed/temp01.dbf
データファイルも一時ファイルも /opt/oracle/oradata/FREE/pdbseed/ 配下にまとまっています。ということは、変換ルールは1組で足ります。
コピー先のディレクトリを OS 側で作っておきます。Oracle はディレクトリを自動作成してくれないので、この手順は必須です。SQL*Plus から抜けずに実行できます。
HOST mkdir -p /opt/oracle/oradata/FREE/lab01
ついでに、この CDB に作れる PDB の上限も見ておきましょう。
SHOW PARAMETER max_pdbs
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
max_pdbs integer 18
この環境では18でした。ラボで1つ作る分にはまったく問題ありません。
PDBを作ってみる
所要時間を測りたいので、SET TIMING ON を有効にしてから実行します。ここが今回いちばんの体感ポイントです。
SET TIMING ON
CREATE PLUGGABLE DATABASE lab01
ADMIN USER labadmin IDENTIFIED BY "Bronze#26ai_Lab"
FILE_NAME_CONVERT = ('/opt/oracle/oradata/FREE/pdbseed/',
'/opt/oracle/oradata/FREE/lab01/');
Pluggable database created.
Elapsed: 00:00:09.29
約9秒で、新しいデータベースが1つ増えました。
非CDB の時代に数十分かけていた作業が、この時間で終わります。これがマルチテナントの高速プロビジョニングです。1棟のマンションが建っていれば、そこに部屋を1つ足すのは新築とは比べものにならないほど手軽、というわけですね。
構文のポイントを2つ補足します。
ADMIN USER 句は省略できません。 PDB$SEED からコピーして PDB を作る場合、その PDB の管理者を必ず1人指定する必要があります。ここで指定したユーザーには、その PDB 限定の管理者ロール(PDB_DBA)が付与されます。新しい部屋を作るときに鍵を渡す相手を決めておく、というイメージです。
FILE_NAME_CONVERT は「コピー元→コピー先」のパス変換ルールです。 PDB$SEED のファイルを読み込んで、パス中の /pdbseed/ を /lab01/ に置き換えた場所に複製する、という指定になっています。この句の存在自体が、PDB がモデルルームの複製として作られていることを物語っています。
作った直後の状態を見てみましょう。
SET TIMING OFF
SELECT con_id, name, open_mode FROM v$pdbs ORDER BY con_id;
CON_ID NAME OPEN_MODE
---------- -------------------------------------------------- ------------
2 PDB$SEED READ ONLY
3 FREEPDB1 READ WRITE
4 LAB01 MOUNTED
LAB01 が CON_ID = 4 で追加されました。ただし OPEN_MODE は MOUNTED です。部屋はできたけれど、まだ鍵が開いていない状態ですね。開けます。
ALTER PLUGGABLE DATABASE lab01 OPEN;
SELECT con_id, name, open_mode FROM v$pdbs ORDER BY con_id;
Pluggable database altered.
CON_ID NAME OPEN_MODE
---------- -------------------------------------------------- ------------
2 PDB$SEED READ ONLY
3 FREEPDB1 READ WRITE
4 LAB01 READ WRITE
READ WRITE になりました。これで使える状態です。
なお、この状態で CDB を再起動すると、LAB01 は MOUNTED に戻ります。開いた状態を記憶させるには ALTER PLUGGABLE DATABASE lab01 SAVE STATE; を実行しますが、今回は最後に削除するので実行しません。「PDB の開閉状態は明示的に保存しないと引き継がれない」とだけ覚えておいてください。
作られたファイルを確認する
#1-3 で扱った内容と繋がる部分です。
SELECT f.con_id, f.file#, f.name
FROM v$datafile f
JOIN v$containers c ON f.con_id = c.con_id
WHERE c.name = 'LAB01';
CON_ID FILE# NAME
---------- ---------- --------------------------------------------------
4 12 /opt/oracle/oradata/FREE/lab01/system01.dbf
4 13 /opt/oracle/oradata/FREE/lab01/sysaux01.dbf
4 14 /opt/oracle/oradata/FREE/lab01/undotbs01.dbf
PDB$SEED と同じ構成のファイルが、lab01 ディレクトリに複製されています。ファイル名はそのままで、ディレクトリだけが変わっていますね。FILE_NAME_CONVERT が働いた結果です。
ここで確認しておきたいのは、制御ファイルと REDO ログは増えていないということです。
SELECT name FROM v$controlfile;
SELECT group#, member FROM v$logfile ORDER BY group#;
先ほどと同じ結果が返ってくるはずです。部屋を1つ増やしても、建物の管理台帳と作業日誌は1セットのまま。
これが「共有するもの/分けるもの」の設計が効いている瞬間です。
接続先を切り替える
作った部屋に移動してみます。
ALTER SESSION SET CONTAINER = lab01;
SHOW CON_NAME
Session altered.
CON_NAME
------------------------------
LAB01
管理人室から LAB01 の部屋に移動しました。この状態で SELECT を実行すると、見えるのは LAB01 の中身だけになります。
ルートに戻ります。
ALTER SESSION SET CONTAINER = CDB$ROOT;
SHOW CON_NAME
Session altered.
CON_NAME
------------------------------
CDB$ROOT
ALTER SESSION SET CONTAINER は管理者が建物内を移動するための手段です。マスターキーを持った管理人が、部屋を渡り歩いているイメージですね。
一方、アプリケーションはこの方法を使いません。サービス名を指定して、最初から目的の部屋に直接入ります。
PDB を作成すると、その PDB 名のサービスが自動的に登録されます。
SELECT con_id, name, pdb FROM v$services ORDER BY con_id;
接続文字列としては ホスト:ポート/サービス名 の形になります。
# 概念の例:FREEPDB1 に直接接続する
$ sqlplus ユーザー名@localhost:1521/freepdb1
この違いは重要です。アプリケーションから見れば、PDB は独立した1つのデータベースにしか見えません。 「実は同じ建物の別の部屋に他のシステムが同居している」ことを、アプリは知る必要がないのです。だからこそ、既存のアプリを修正せずに集約できます。
利点③
部屋ごと引っ越せる(アンプラグ/プラグ)
PDB の「P」は Pluggable(プラグで抜き差しできる) の頭文字です。名前のとおり、PDB は建物から抜き取って、別の建物に差し込めるようになっています。
- アンプラグ:PDB を CDB から切り離し、その PDB の情報をまとめたメタデータ・ファイル(XML)を出力する
- プラグ:そのメタデータ・ファイルとデータファイルを使って、別の CDB に組み込む
イメージとしては、部屋の中身をコンテナごとトラックに積んで、別のマンションの空き部屋にそのまま設置するようなものです。荷ほどきも模様替えも不要で、住人(アプリケーション)から見れば引っ越し前とまったく同じ部屋です。
コマンドの形だけ示しておきます(今回は実行しません)。
-- ※実行しません。イメージとして掲載しています
ALTER PLUGGABLE DATABASE lab01 CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE lab01 UNPLUG INTO '/tmp/lab01.xml';
DROP PLUGGABLE DATABASE lab01 KEEP DATAFILES;
-- 移動先の CDB で
CREATE PLUGGABLE DATABASE lab01 USING '/tmp/lab01.xml';
DROP に KEEP DATAFILES が付いている点がポイントです。定義だけを消して、荷物は残す。 だから別の建物で組み立て直せるわけです。
ここで、さきほど確認したローカルUNDOが効いてきます。UNDO 表領域が PDB ごとに分かれているからこそ、部屋の中身を過不足なく持ち出せるのです。もし UNDO が建物側に1つしかなければ、引っ越しのたびに「この部屋の分だけ取り出す」という面倒な作業が発生していました。
この可搬性が活きるのは、たとえばこんな場面です。
- 開発環境で作った PDB を、そのまま検証環境の CDB に移す
- 古いバージョンの CDB から、新しいバージョンの CDB へ PDB を移してアップグレードする
- 負荷の高い PDB だけを、性能の良いサーバーの CDB へ移す
実際の操作は、PDB のクローズ、XML ファイルの受け渡し、互換性チェック(DBMS_PDB.CHECK_PLUG_COMPATIBILITY)など、考慮すべき点が多くあります。
Bronze の範囲では「こういうことができる」という理解で十分で、詳細は上位資格の範囲です。今回は概念の紹介にとどめます。
利点④
まとめて管理できる
PDB が何個あっても、管理者が相手にするのは1つの CDB です。
- バックアップ:RMAN で CDB を対象にすれば、配下の PDB がまとめて対象になる(PDB 単位の指定も可能)
- パッチ適用:Oracle ホームに1回当てれば、その CDB の全 PDB に効く
- アップグレード:CDB 単位で実施できる
- 監視:1つのインスタンスを見れば全体が見える
一戸建て30軒の屋根を1軒ずつ修理して回るのと、マンション1棟の屋上を1回直すのとの違いです。
そして日々の管理で効いてくるのが、CDB_ ビューによる横断参照です。
全部屋をまとめて眺める
CDB ルートから、全 PDB のデータファイル構成を一度に確認してみます。
SELECT con_id, tablespace_name, COUNT(*) AS files
FROM cdb_data_files
GROUP BY con_id, tablespace_name
ORDER BY con_id, tablespace_name;
CON_ID TABLESPACE_NAME FILES
---------- ------------------------------ ----------
1 SYSAUX 1
1 SYSTEM 1
1 UNDOTBS1 1
3 SYSAUX 1
3 SYSTEM 1
3 UNDOTBS1 1
4 SYSAUX 1
4 SYSTEM 1
4 UNDOTBS1 1
1回の問い合わせで、ルートも FREEPDB1 も LAB01 もまとめて見えました。
非CDB が3つ並んでいたら、3回別々に接続して同じ SQL を打つ必要があったところです。
各コンテナが SYSTEM / SYSAUX / UNDOTBS1 を1つずつ持っていることも読み取れます。
部屋ごとに独立した設備を持っているという構造が、そのまま数字に出ていますね。
CDB_ と DBA_ と V$ の使い分け
#1-3 で V$ と DBA_ の違いを扱いました。マルチテナントでは、ここに CDB_ が加わります。
| 接頭辞 | 見えるもの | 由来 |
|---|---|---|
V$ |
インスタンスの現在の状態 | メモリ上の動的情報 |
DBA_ |
いま接続しているコンテナの情報 | データ・ディクショナリ |
CDB_ |
CDB 内の全コンテナの情報 | データ・ディクショナリ |
CDB_ ビューには DBA_ ビューにない CON_ID 列があります。「どの部屋の話なのか」を区別する必要があるからです。
覚え方としては、DBA_ は自分の部屋の中を見る、CDB_ は建物全体を見渡す、と考えると分かりやすいと思います。
そして、この見え方はどこから実行するかで変わります。PDB の中で CDB_ ビューを問い合わせても、他の部屋の情報は見えません。部屋の中から他人の部屋は覗けないのです。当たり前ですが、セキュリティ上とても重要な性質です。
もうひとつ、上の結果で CON_ID = 2(PDB$SEED)が出てきていない点にも触れておきます。CDB_ ビューは通常、モデルルームであるシードを対象に含めません。実データの入っていないひな型が集計に混じっても混乱するだけ、ということですね。
共通ユーザーとローカルユーザー
マルチテナントでは、ユーザーが2種類に分かれます。これもマンションで考えると腑に落ちます。
-
共通ユーザー(Common User)=管理会社の社員
建物全体で認識され、すべての部屋に存在します。SYSやSYSTEMがこれにあたります。管理者が自分で作る場合は、ユーザー名をC##で始める必要があります(例:C##ADMIN)。マスターキーを持っている人、というイメージです。 -
ローカルユーザー(Local User)=その部屋の住人
特定の PDB の中にだけ存在します。他の部屋からは、そんな人がいることすら見えません。アプリケーションが使うユーザーは基本的にこちらです。
C## という接頭辞のルールには理由があります。共通ユーザーは全部屋に存在するので、もし接頭辞がなければ、ある部屋の住人が偶然同じ名前を使ってしまったときに衝突します。「管理会社の社員は名札に C## を付ける」と決めておけば、住人の名前とぶつかりません。
ユーザーの種別を確認する
CREATE PLUGGABLE DATABASE で指定した LABADMIN が、どちらのユーザーになっているか見てみましょう。CDB ルートで実行します。
SELECT username, common, con_id
FROM cdb_users
WHERE username IN ('SYS','SYSTEM','LABADMIN')
ORDER BY con_id, username;
USERNAME COM CON_ID
-------------------- --- ----------
SYS YES 1
SYSTEM YES 1
SYS YES 3
SYSTEM YES 3
LABADMIN NO 4
SYS YES 4
SYSTEM YES 4
きれいに分かれました。
SYS と SYSTEM は CON_ID 1・3・4 のすべてに現れ、COMMON が YESです。管理会社の社員は全部屋に出入りできる、というわけですね。
LABADMIN は CON_ID = 4(LAB01)にしか存在せず、COMMON は NOです。ADMIN USER 句で作られる管理者は、その PDB のローカルユーザーなのです。「その部屋の管理を任された住人」であって、建物全体の管理者ではありません。
作ったPDBを片付ける
環境を元の状態に戻します。必ず実施してください。
PDB を削除するには、まず閉じる必要があります。人が住んだままの部屋は取り壊せません。
ALTER PLUGGABLE DATABASE lab01 CLOSE IMMEDIATE;
Pluggable database altered.
削除します。
DROP PLUGGABLE DATABASE lab01 INCLUDING DATAFILES;
Pluggable database dropped.
INCLUDING DATAFILES を忘れないでください。 これを付けないと(あるいは KEEP DATAFILES を指定すると)、PDB の定義だけが消えてデータファイルはディスクに残り続けます。利点③で見たとおり、これは「引っ越しのために荷物を残す」ための仕様です。今回は引っ越さないので、荷物ごと処分します。
元に戻ったことを確認します。
SELECT con_id, name, open_mode FROM v$containers ORDER BY con_id;
CON_ID NAME OPEN_MODE
---------- -------------------------------------------------- ------------
1 CDB$ROOT READ WRITE
2 PDB$SEED READ ONLY
3 FREEPDB1 READ WRITE
はじめと同じ状態に戻りました。
最後に、空になったディレクトリを削除しておきます。ファイルは消えていますが、ディレクトリ自体は残るためです。
HOST rmdir /opt/oracle/oradata/FREE/lab01
これで完全に元通りです。
まとめ
今回はマルチテナント・アーキテクチャの利点を、PDB を実際に作りながら確認しました。
用語
| 用語 | マンションのたとえ | 実機での確認方法 |
|---|---|---|
| CDB | マンションの建物(FREE) |
SELECT instance_name FROM v$instance; |
| PDB | 部屋(FREEPDB1) |
SELECT pdb_name FROM cdb_pdbs; |
| CDB$ROOT | 共用部・管理人室(CON_ID=1) |
SHOW CON_NAME |
| PDB$SEED | モデルルーム(読み取り専用) |
V$CONTAINERS の OPEN_MODE
|
| 共通ユーザー | 管理会社の社員(C##) |
CDB_USERS.COMMON = 'YES' |
| ローカルユーザー | 部屋の住人 | CDB_USERS.COMMON = 'NO' |
| ローカルUNDO | 部屋ごとのゴミ箱 | DATABASE_PROPERTIES |
主要コマンド
| 操作 | コマンド |
|---|---|
| 現在地の確認 | SHOW CON_NAME |
| PDB作成 | CREATE PLUGGABLE DATABASE 名前 ADMIN USER ... |
| PDBオープン | ALTER PLUGGABLE DATABASE 名前 OPEN; |
| 開閉状態の保存 | ALTER PLUGGABLE DATABASE 名前 SAVE STATE; |
| コンテナ切り替え | ALTER SESSION SET CONTAINER = 名前; |
| PDBクローズ | ALTER PLUGGABLE DATABASE 名前 CLOSE IMMEDIATE; |
| PDB削除 | DROP PLUGGABLE DATABASE 名前 INCLUDING DATAFILES; |
次回予告
次回 #1-5 では、第1章の残り2項目である「Oracle AI Database 26ai の新機能の概要」と「26ai の特徴と利点」を扱います。ここまで見てきた土台の上に、26ai で何が新しくなったのかを重ねていく回です。
参考
- Oracle AI Database 26ai ドキュメント・ライブラリ
- Oracle AI Database 概要 - CDBおよびPDB:CDBおよびPDB
- Oracle Multitenant 管理者ガイド:PDBの作成
- Oracle AI Database 管理者ガイド:データベースの構造、スキーマ・オブジェクト等
- Oracle AI Database リファレンス:静的データディクショナリ・ビュー