3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Oracle】バグかと思ったら、自分で仕掛けた○○○だった話 pdb_to_apppdb.sql

3
Last updated at Posted at 2026-06-29

事件は突然に

ある日アプリケーション・コンテナの検証していたところ、pdb_to_apppdb.sql の実行中に、見慣れたエラーが見慣れない場所で発生しました。

SQL> @?/rdbms/admin/pdb_to_apppdb.sql
SQL> SET FEEDBACK 1
SQL> SET NUMWIDTH 10

-----------------------------------<中略>-----------------------------------

SQL> alter system flush shared_pool;
alter system flush shared_pool
*
1でエラーが発生しました。:
ORA-01031: 権限が不足しています

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0との接続が切断されました。

実行ユーザーは SYSDBA でした。

「SYSDBAなのに権限不足とは?」

「バグでは?」

「内部スクリプトが怪しいのでは?」

そんなふうにOracleを疑い続けた結果、犯人はOracleではありませんでした。

過去の自分でした。

環境

今回の検証環境は以下です。

  • Oracle Database 19c
  • Version 19.3.0.0
  • アプリケーション・ルート:APPROOT
  • アプリケーションPDB:APPPDB1
  • APPPDB1 は通常のPDBをクローンして作成

コンテナの構成は以下です。

CDB$ROOT
  ├─ PDB1 --クローン元
  └─ APPROOT
       ├─ APPROOT$SEED
       └─ APPPDB1 -- PDB1をクローンして作成したアプリケーション・コンテナ

発生した事象

今回、PDBをクローン元としてアプリケーションPDBを作成する検証をしていました。

SQL> ALTER SESSION SET CONTAINER=APPROOT;

セッションが変更されました。

SQL> CREATE PLUGGABLE DATABASE APPPDB1 FROM PDB1;

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

通常のPDBとして作成した APPPDB1 をアプリケーションPDBへ変換するため、以下を実行しました。

ALTER SESSION SET CONTAINER=APPPDB1;

@?/rdbms/admin/pdb_to_apppdb.sql

スクリプトは順調に進んでいるように見えました。

ビューが作成され、内部表が更新され、アプリケーション・ルートとの同期も行われています。

と思った直後、冒頭のエラーが発生しました。

急にSQL Plus追い出されました。

SYSDBAなのに権限不足?

実行時の接続は以下です。

sqlplus / as sysdba

当然、最初に疑ったのは接続ミスです。

SQL> show user
ユーザーは"SYS"です。

SYSです。

さらに、

SQL> SELECT SYS_CONTEXT('USERENV','ISDBA') FROM DUAL;

SYS_CONTEXT('USERENV','ISDBA')
--------------------------------------------------------------------------------
TRUE

しっかりSYSDBAです。

にもかかわらず、

ALTER SYSTEM FLUSH SHARED_POOL;

でORA-01031が発生しています。

この時点で頭の中はこうなりました。

……え?
SYSDBAで権限不足?

SYSDBAが権限不足なら、いったい誰なら権限が足りるのか。

変換状況を確認

スクリプトが途中終了したため、変換自体が失敗したと思いました。

しかし、アプリケーション・ルートで確認すると、少し不思議な状態になっていました。

SQL> ALTER SESSION SET CONTAINER=APPROOT;

セッションが変更されました。

SQL> SELECT pdb_name,
       application_pdb,
       status
FROM   dba_pdbs
WHERE  pdb_name='APPPDB1';

PDB_NAME  APPLICATION_PDB  STATUS
--------- ---------------- ----------
APPPDB1   YES              NORMAL

APPLICATION_PDBYES です。

さらに、APPPDB1でアプリケーション・ルート名を確認します。

SQL> ALTER SESSION SET CONTAINER=APPPDB1;

SQL> SELECT SYS_CONTEXT('USERENV','APPLICATION_NAME') FROM DUAL;

SYS_CONTEXT('USERENV','APPLICATION_NAME')
--------------------------------------------------------------------------------
APPROOT

APPROOTとの関連付けもできています。

「成功しているのでは?」

と思い、PDBを通常モードで開き直しました。

ALTER SESSION SET CONTAINER=CDB$ROOT;

ALTER PLUGGABLE DATABASE APPPDB1 CLOSE IMMEDIATE;
ALTER PLUGGABLE DATABASE APPPDB1 OPEN;

すると、次の警告が表示されました。

警告: PDBが変更されましたが、エラーがあります。

確認すると、APPPDB1は制限モードで開いています。

SELECT name,
       open_mode,
       restricted
FROM   v$pdbs
WHERE  name='APPPDB1';
NAME     OPEN_MODE   RESTRICTED
-------- ----------- ----------
APPPDB1  READ WRITE  YES

Application PDBにはなっていますが、何かが終わっていません。

PDB_PLUG_IN_VIOLATIONSを確認

PDB関連で何かがおかしいときは、まず PDB_PLUG_IN_VIOLATIONS を確認します。

SELECT cause,
       type,
       message,
       status
FROM   pdb_plug_in_violations
WHERE  name='APPPDB1'
ORDER BY time;

結果:

CAUSE
------------------------------------------
Non-Application PDB to Application PDB

TYPE
---------
ERROR

MESSAGE
------------------------------------------------------------
Non-Application PDB plugged in as an Application PDB,
requires pdb_to_apppdb.sql be run.

STATUS
---------
PENDING

Oracleからは、

pdb_to_apppdb.sql を実行してください。

と言われています。

実行しました。
実行した結果、途中で追い出されたのです。

バグを疑う

困ったので、チャッピー君へ質問してみました。
回答は、

PENDING が消えずに再度 ORA-01031 で落ちるなら、19.3の不具合寄りなので、次はスクリプトをコピーして alter system flush shared_pool; の行だけ一時的にコメントアウトして通す方法を検討します。

ここからバグを疑い始めました。

環境は19.3.0.0です。

19cの初期リリースなので、アプリケーション・コンテナ周りの不具合があっても不思議ではありません。

さらに、エラー直前のソースコードを見ると、以下のようになっています。

ALTER SESSION SET "_APPLICATION_SCRIPT"=TRUE;

ALTER SYSTEM FLUSH SHARED_POOL;

pdb_to_apppdb.sql から呼び出される loc_to_common2.sql の中で、内部パラメータを有効にした直後にエラーが発生しています。

そのため、次のような仮説を立てました。

  • _APPLICATION_SCRIPT=TRUE のときだけ権限チェックがおかしくなる
  • Oracle 19.3固有の不具合?
  • PDB内から FLUSH SHARED_POOL を実行できない
  • スクリプト自体に不具合がある

かなりOracleを疑っています。

Oracleさん、すみませんでした。

一時は、以下をコメントアウトして回避することも考えました。

しかし、スクリプトを変更する前に、

そもそも、なぜSYSDBAでORA-01031になるのか?

を確認することにしました。

コメントアウトして動いたとしても、それは解決ではなく、エラー箇所を通らないようにしただけです。

ここで、クローン元PDBに何を設定していたかを思い出しました。

犯人は自分だった

以前クローン元のPDBには、検証目的でPDBへロックダウンプロファイルを設定していました。

ロックダウン・プロファイルは、PDB内で実行できる文や機能を制限する仕組みです。

例えば、以下のように ALTER SYSTEM を禁止できます。

CREATE LOCKDOWN PROFILE PDB_LOCKDOWN_PROFILE;

ALTER LOCKDOWN PROFILE PDB_LOCKDOWN_PROFILE DISABLE STATEMENT = ('ALTER SYSTEM');

PDBに適用する場合は、次のように設定します。

ALTER SYSTEM SET PDB_LOCKDOWN='PDB_LOCKDOWN_PROFILE';

今回、APPPDB1はこのPDBを元にクローンして作成していました。

そしてクローン先のAPPPDB1でも、ロックダウン・プロファイルが有効な状態になっていました。

確認します。

ALTER SESSION SET CONTAINER=APPPDB1;

SHOW PARAMETER PDB_LOCKDOWN

NAME          TYPE    VALUE
------------- ------- --------------------
pdb_lockdown  string  PDB_LOCKDOWN_PROFILE

いました。

ずっと原因はそこにいました。

なぜSYSDBAでもORA-01031になったのか

pdb_to_apppdb.sql の内部では、次の文が実行されます。

ALTER SYSTEM FLUSH SHARED_POOL;

しかし、APPPDB1に適用されているロックダウン・プロファイルでは、ALTER SYSTEM を禁止していました。

そのため、SYSDBAで接続していても、APPPDB1内で実行された文は拒否されます。

結果として、

ORA-01031: 権限が不足しています

が発生していました。

つまり、バグでも、SYSDBA権限の消失でもありません。

ロックダウン・プロファイルが正常に仕事をしていただけです。

正常に仕事をした結果、作業が失敗しました。

原因の流れ

今回の事象を整理すると、以下の流れになります。

クローン元PDBにロックダウン・プロファイルを設定
        ↓
APPPDB1にも設定が引き継がれる
        ↓
pdb_to_apppdb.sqlを実行
        ↓
スクリプト内部でALTER SYSTEM FLUSH SHARED_POOLを実行
        ↓
ロックダウン・プロファイルがALTER SYSTEMを拒否
        ↓
ORA-01031
        ↓
スクリプトが途中終了

すべてつながりました。

対処方法

今回は検証環境のため、変換作業中だけロックダウン・プロファイルを解除しました。

ALTER SYSTEM SET PDB_LOCKDOWN='' SCOPE=BOTH;

再度スクリプトを実行して正常終了すれば、原因がLockdown Profileであることを確認できます。

pdb_to_apppdb.sqlを再実行

APPPDB1をUPGRADEモードで開きます。

ALTER SESSION SET CONTAINER=CDB$ROOT;

ALTER PLUGGABLE DATABASE APPPDB1 CLOSE IMMEDIATE;

ALTER PLUGGABLE DATABASE APPPDB1 OPEN UPGRADE;

APPPDB1へ切り替え、スクリプトを再実行します。

ALTER SESSION SET CONTAINER=APPPDB1;

@?/rdbms/admin/pdb_to_apppdb.sql

今回は、ALTER SYSTEM FLUSH SHARED_POOL でORA-01031は発生せず、最後まで完了しました。

まとめ:今回の反省点

今回の最大の反省点は、

『バグを疑う前に、自分が設定した項目を思い出そう』 です。

特にORA-01031を見ると、次のような点に意識が向きがちでした。

  • ユーザーに権限がない
  • SYSDBAで接続していない
  • 必要なロールが有効になっていない
  • コンテナを間違えている

しかし、マルチテナント環境ではロックダウン・プロファイルによって、PDB単位でSQL文や機能が制限されている可能性があります。

SYSDBAだから何でもできるとは限りません。

エラーメッセージだけを見ると権限付与に目が行きますが、マルチテナント環境ではPDB単位の制限も忘れずに確認したいところです。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?