お仕事ではOracleDBに触れることが多いです。基幹データベースはOracleDBで構築されており、度重なる移行を経ており、、私が知っているだけでもすでに4世代目の基盤上で動いています。
今回はそのデータベースを、オンプレに配備されているOracleDBからOCI(Oracle Cloud Infrastructure)に構築されたOracleDBに移行する作業中に見つかった問題。現時点でも根本原因は不明だが回避策はわかったものです。
前提
- 移行元・移行先はOracle Database 12c R1。ただし移行元は数年前までは11g、そのまた数年前までは…という具合にバージョンアップ&移行を繰り返してきました。
- 移行元も移行先も、複数のOracleDBインスタンス(正確に言うと、移行先ではインスタンスではなく同一CDB上の複数のPDB)が存在。
- インスタンス同士はDBLINKにより接続されており、片方のインスタンスからもう片方のインスタンスのオブジェクトが参照可能な状態。
- インスタンスAのテーブルはインスタンスBからDBLINKを通じてアクセス可能。
- インスタンスBには多数のMV(マテリアライズドビュー)が存在。
- それらMVの定義内のクエリでインスタンスAのテーブルを参照するものが多数存在。
- 移行元のOracleDBインスタンスでは、検証環境のシステム群(DBのユーザー)の洗い替え(trunkからbranchへの逆マージ)の都度、Masterの役割を持つスキーマをエクスポートし、別名でインポートすることでDBオブジェクトとレコードの洗い替えをする運用が長年行われてきた。
- 移行はDBLINK経由で移行元DBインスタンスを移行先PDBとしてクローンするという手法で実施。
- 移行元インスタンスに存在したユーザースキーマで、移行先PDBでは不要となるユーザースキーマは、クローン後にdrop。
事象
移行先のOracleDBのPDB B(移行元のインスタンスBに相当)側でMVリフレッシュを行ったところ、以下のようなエラーが発生。
行1でエラーが発生しました。:
ORA-01435: ユーザーが存在しません。
ORA-06512: "SYS.DBMS_SNAPSHOT_UTL", 行364
ORA-06512: "SYS.DBMS_SNAPSHOT_UTL", 行446
ORA-06512: "SYS.DBMS_SNAPSHOT", 行2821
ORA-06512: "SYS.DBMS_SNAPSHOT", 行3058
ORA-06512: "SYS.DBMS_SNAPSHOT", 行3017
ORA-06512: 行1
MVの定義情報を引き出して確認すると、このMVの定義で用いされているDBLINKには問題なし。DBLINK定義時に指定される認証情報は正しく、DBLINKにより参照されるユーザースキーマとそのオブジェクトも健在。手でクエリを実行すれば参照は可能。
原因
不明。
ただおそらく「前提」で述べた移行元DBにおける洗い替えの運用により、データディクショナリのデータ不整合が生じている模様。
回避策
- PDB B側で、dba_snapshotsテーブルを参照。
- dba_snapshots.master_ownerカラムの内容がMVの定義情報(のクエリに含まれるDBLINK経由の参照先)と不一致になっているものを抽出。
- 「前提」でも述べた「不要なユーザースキーマ」としてdropしていたものに該当していたので、このスキーマをPDB A(インスタンスAに相当)に新規作成、さらにそのスキーマ内にMVから参照されるのと同名のテーブルを新規作成。
- この状態でMVリフレッシュをトライしたところ成功。
なお、この新規作成するテーブルは名前の一致だけが重要で、カラムや制約、索引などはでたらめで問題ない。。