5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ADBの手動バックアップをADBだけで取得する

Last updated at Posted at 2025-12-15

はじめに

Autonomous AI Database (ADB) は日々自動的にバックアップを取得するようになっているので、バックアップについて無意識で利用していると思います。
image.png
[引用] Autonomous AI Database Serverless 技術詳細 / adb-s_technical_detail_jp

自動バックアップで取得されるバックアップは、データベース全体をまるっと1つのバックアップとして取得します。
そのため、例えばこのテーブルだけ2日前に戻したいなど、細かいリストアはできません。
ADBにスキーマ名で区別された複数のシステムが乗っていて、そのシステムを独立してリストアさせたいという要件がある場合は、手動でバックアップを取得する必要があります。

Autonomous AI Databaseでの手動バックアップ

今回紹介する取得方法は2つあります。

(1) ClientサーバーからData Pumpの利用
(2) DBMS_DATAPUMPパッケージの利用

一般的な方法は(1)のClinentサーバーとしてcomputeを用いて、そこからData Pumpを実行させる方法です。
(1)で実行する場合、Data Pump実行するためだけにcomputeを立てる必要があります。
そしてcomputeに設定したCPU数で割り当てられる帯域が決まるので、バックアップの取得に時間が掛かる場合のボトルネックとなる可能性もあります。

それを避ける方法として、ADBのパッケージを利用してバックアップを取得する方法があります。
まず(1)の一般的な方法を説明させていただきますので、それを踏まえて(2)の方法を確認していただければと思います。

(1) ClientサーバーからData Pumpの利用

この方法は他の方の記事にもあるので、そちらも参照してください。
今回の検証する時に教科書として勉強させていただきました。ありがとうございました。

今回想定しているのは、以下のような構成です。

ADB1で特定のスキーマ名のバックアップだけを取得して、ADB2にそのバックアップファイルを使ってリストアします。
image.png
今回はHR_APPがADB1に持つオブジェクトをADB1にいるEXP_USERがエクスポートして、ダンプファイルを生成します。
そのダンプファイルをADB2にいるIMP_USERがインポートして、HR_APPのオブジェクトをADB1からADB2に移行させるという順番で実行します。
その手順はこちらです。

(1-1) サンプルスキーマ・オブジェクトの準備
(1-2) クレデンシャルの発行
(1-3) Data Pumpを利用したエクスポート
(1-4) Data Pumpを利用したインポート

こちらの手順するためには、computeからADBにwalletを利用して接続する必要があります。
下記を参考にcomputeからADBにはwallet経由で接続できるようにしておいてください。

(1-1) サンプルスキーマ・オブジェクトの準備

まず、エクスポート元であるADB1で作業を行います。
computeからADBに接続してコマンドラインで実行しても、ADBコンソールにあるSQLワークシートから実行していただいても構いません。

adminユーザーでログインします。
オブジェクト所有スキーマHR_APP、エクスポート実行スキーマEXP_USERの作成

CREATE USER HR_APP IDENTIFIED BY "[Password]" QUOTA UNLIMITED ON DATA;
CREATE USER EXP_USER IDENTIFIED BY "[Password]" QUOTA UNLIMITED ON DATA;

HR_APPへの権限付与
サンプルオブジェクト作成のため多数権限を付与しましたが、本番環境では必要なものだけを付与してください。
(本手順でも実際にはテーブルしか作成しません。)

GRANT CREATE SESSION TO HR_APP;
GRANT CREATE TABLE TO HR_APP;
GRANT CREATE VIEW TO HR_APP;
GRANT CREATE SEQUENCE TO HR_APP;
GRANT CREATE PROCEDURE TO HR_APP;
GRANT EXECUTE ON DBMS_CLOUD TO HR_APP;

EXP_USERへの権限付与

GRANT EXECUTE ON DBMS_CLOUD TO HR_APP;

HR_APPサンプルテーブルの作成
今回はHR_APPに切り替えて実行しました。
SYSユーザーから実行する際には、テーブル名をEMPLOYEESHR_APP.EMPLOYEEに変更してください。

CREATE TABLE EMPLOYEES (
  EMP_ID NUMBER PRIMARY KEY,
  NAME VARCHAR2(50),
  DEPARTMENT VARCHAR2(50),
  SALARY NUMBER
);

作成したテーブルにサンプルデータを入れます。

INSERT INTO EMPLOYEES VALUES (1, 'Alice', 'HR', 5000);
INSERT INTO EMPLOYEES VALUES (2, 'Bob', 'HR', 5200);
COMMIT;

続いてインポート先のADB2でインポートユーザーの準備をします。
インポート実行スキーマIMP_USERの作成

CREATE USER IMP_USER IDENTIFIED BY "[Password]" QUOTA UNLIMITED ON DATA;

IMP_USERへの権限付与

GRANT EXECUTE ON DBMS_CLOUD TO IMP_USER;

(1-2) クレデンシャルの作成

ADB1でエクスポートして生成されるダンプファイルをADB2に渡す際、オブジェクトストレージに格納して渡します。
そのため、ADB1, ADB2それぞれがオブジェクトストレージに接続できるようにクレデンシャルを発行します。

認証トークンの発行・確認
OCIコンソールのホームからユーザー名を選択します。
image.png
認証トークンの画面に遷移し、トークンの生成を選択します。
image.png
使用するトークン名を記載します。
image.png
トークンが生成されると「***」として記載があるので、表示を選択します。
そこで初めてトークンを確認することができます。
トークンは二度と表示されないので、生成されたトークンをコピーしてメモしておきます。
メモができたら閉じます。
image.png

クレデンシャルの作成
ADB1, ADB2それぞれで同じ手順を行います。
ADB1の場合はEXP_USER、ADB2の場合はIMP_USERでログインします。
以下のPL/SQLでクレデンシャルを発行します。

BEGIN
  DBMS_CLOUD.CREATE_CREDENTIAL(
    credential_name => 'EXPORT_CRED1',
    username => '[user_name]',
    password => '[token(先ほど確認した認証トークンの中身)]'
  );
END;
/

(1-3) Data Pumpを利用したエクスポート

オブジェクトストレージのURIの確認
ダンプファイルを格納する先を指定する際に格納先のURLが必要になります。
OCIコンソールからバケットを選択します。
image.png
使えるバケットがあれば、そのバケットを使用します。
image.png
使えるものがなければ、バケットの作成から作成します。
バケット名を入力して作成してください。(デフォルト名でも問題ないです。)
image.png
オブジェクトの詳細からURIを確認します。
image.png
新しいURIを使用します。
https://・・・/o/の部分をメモします
image.png

ADB1からエクスポート
ADB1へ接続できるcomputeにログインします。
EXP_USERHR_APPのオブジェクトを全てエクスポートして、TEST_exp01.dmpというダンプファイルをオブジェクトストレージに生成しするように指定します。

expdp EXP_USER/[Password]@[ADB1への接続識別子] \
  DIRECTORY=DATA_PUMP_DIR \
  credential=EXPORT_CRED1 \
  dumpfile=[オブジェクトストレージのURI] https://***/o/TEST_exp%U.dmp\
  LOGFILE=EXP_USER_exp.log \
  SCHEMAS=HR_APP \
  PARALLEL=1

実行した際のログはこのようになりました。

[opc@compute ~]$ expdp hr_app/***@soltybackuptest_high \
  DIRECTORY=DATA_PUMP_DIR \
  credential=EXPORT_CRED1 \
  dumpfile=https://objectstorage***/o/TEST_exp%U.dmp\
  LOGFILE=hr_app_exp.log \
  SCHEMAS=HR_APP \
  PARALLEL=1

Export: Release 21.0.0.0.0 - Production on Wed Nov 5 10:30:25 2025
Version 21.13.0.0.0

Copyright (c) 1982, 2024, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 23ai Enterprise Edition Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems
Starting "EXP_USER"."SYS_EXPORT_SCHEMA_01":  exo_user/********@***_high DIRECTORY=DATA_PUMP_DIR credential=EXPORT_CRED1 dumpfile=https://***/b/bucket-20251105-1033/o/TEST_exp%U.dmp LOGFILE=exp_user_exp.log SCHEMAS=HR_APP PARALLEL=1 
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA/LOGREP
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCOBJ/SCHEDULER
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/POST_SCHEMA/PROCACT_SCHEMA/LBAC_EXP
. . exported "HR_APP"."EMPLOYEES"                          6.5 KB       2 rows
ORA-39173: Encrypted data has been stored unencrypted in dump file set.
Master table "HR_APP"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for EXP_USER.SYS_EXPORT_SCHEMA_01 is:
  https://***/o/TEST_exp01.dmp
Job "EXP_USER"."SYS_EXPORT_SCHEMA_01" successfully completed at Wed Nov 5 10:31:13 2025 elapsed 0 00:00:46

ログからうまくいった様子がわかります!
ダンプファイルができているのか確認しましょう。

バケットの中身を確認
ダンプファイルが生成できているかをバケットの中を見て確認します。
生成されていることが確認できました!
image.png
このときにオブジェクト詳細を確認して、ダンプファイルのURIを確認しておきます。

(1-4) Data Pumpを利用したインポート

先ほどエクスポートする際に使用したcomputeから、次はADB2へのインポートを実行します。

impdp IMP_USER/[Password]@[ADB2への接続識別子] \
  credential=EXPORT_CRED1 \
  dumpfile=[ダンプファイルのURI]https://***/o/TEST_exp01.dmp \
  table_exists_action=append \
  logfile=import.log \
  directory=data_pump_dir

作業時のログはこちらです。

[opc@compute ~]$ impdp IMP_USER/***@***_high \
  credential=EXPORT_CRED1 \
  dumpfile=https://***/o/TEST_exp01.dmp \
  table_exists_action=append \
  logfile=import.log \
  directory=data_pump_dir

Import: Release 21.0.0.0.0 - Production on Thu Nov 6 01:05:06 2025
Version 21.13.0.0.0

Copyright (c) 1982, 2024, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 23ai Enterprise Edition Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems
ORA-39154: Objects from foreign schemas have been removed from import
Master table "IMP_USER"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "IMP_USER"."SYS_IMPORT_FULL_01":  imp_user/********@***_high credential=EXPORT_CRED1 dumpfile=https://***/o/TEST_exp01.dmp table_exists_action=append logfile=import.log directory=data_pump_dir 
Job "IMP_USER"."SYS_IMPORT_FULL_01" successfully completed at Thu Nov 6 01:05:11 2025 elapsed 0 00:00:03

最後のメッセージから問題なくインポートできていそうです。
ADB2にからテーブルが入っているか確認します。
今回はHR_APPユーザーごとインポートしたので、ADB2でHR_APPユーザーとしてログインします。
そして(1-1)で作成したEMPLOYEEテーブルが入っているのかを確認します。

SQL> SELECT * FROM EMPLOYEES;

    EMP_ID NAME            DEPARTMENT           SALARY
---------- --------------- ---------------- ----------
         1 Alice           HR                     5000
         2 Bob             HR                     5200

ADB1に格納したテーブルをADB2でも確認することができました!

(2) DBMS_DATAPUMPパッケージの利用

Oracle GoldenGateに関して書かれたこちらのドキュメント内に、DBMS_DATABUMPパッケージを利用してエクスポートしている記事がありました。

ここに書いてある方法でできるのか気になったので、試してみました。

手順や構成のイメージは先ほどの(1)と大きく変わりませんが、computeを必要としない部分が大きな違いです。
image.png

(2-1) サンプルスキーマ・オブジェクトの準備
(2-2) クレデンシャルの発行
(2-3) DBMS_DATAPUMPパッケージを利用したエクスポート
(2-4) DBMS_DATAPUMPパッケージを利用したインポート

(2-1) サンプルスキーマ・オブジェクトの準備

(1-1)の手順とほぼ同じなので、そちらを参照してください。
今回はエクスポートとインポートをパッケージで実行するため、'EXP_USER'とIMP_USERを用意する必要はありません。
インポートする際に'HR_APP'スキーマのオブジェクトを'FIN_APP'スキーマのオブジェクトとしてリマップしたので、'FIN_APP'スキーマを作成します。

CREATE USER FIN_APP IDENTIFIED BY "[Password]" QUOTA UNLIMITED ON DATA;

(2-2) クレデンシャルの発行

こちらも(1-2)の手順と全く同じなので、そちらを参照してください。

(2-3) DBMS_DATAPUMPパッケージを利用したエクスポート

先ほど紹介したドキュメントのPL/SQLの内で必要な部分のみを変更します。
こちらは'HR_APP'スキーマのオブジェクトがあるADB1で実行します。

DECLARE
ind NUMBER;              -- Loop index
h1 NUMBER;               -- Data Pump job handle
percent_done NUMBER;     -- Percentage of job complete
job_state VARCHAR2(30);  -- To keep track of job state
le ku$_LogEntry;         -- For WIP and error messages
js ku$_JobStatus;        -- The job status from get_status
jd ku$_JobDesc;          -- The job description from get_status
sts ku$_Status;          -- The status object returned by get_status

BEGIN
-- Create a (user-named) Data Pump job to do a schema export.
h1 := DBMS_DATAPUMP.OPEN('EXPORT','SCHEMA',NULL,'SRC_OCIGGLL_EXPORT','LATEST');

-- Specify a single dump file for the job (using the handle just returned
-- and a directory object, which must already be defined and accessible
-- to the user running this procedure.
DBMS_DATAPUMP.ADD_FILE(h1,'https://***/o/SRC_OCIGGLL.dmp','EXPORT_CRED1','100MB',DBMS_DATAPUMP.KU$_FILE_TYPE_URIDUMP_FILE,1);
-- ★ここのオブジェクトURIの変更が必要

-- A metadata filter is used to specify the schema that will be exported.
DBMS_DATAPUMP.METADATA_FILTER(h1,'SCHEMA_EXPR','IN (''HR_APP'')');
-- ★エクスポートしたいスキーマの指定が必要

-- Start the job. An exception will be generated if something is not set up properly.
DBMS_DATAPUMP.START_JOB(h1);

-- The export job should now be running. In the following loop, the job
-- is monitored until it completes. In the meantime, progress information is displayed.
percent_done := 0;
job_state := 'UNDEFINED';
while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
  dbms_datapump.get_status(h1,dbms_datapump.ku$_status_job_error + dbms_datapump.ku$_status_job_status + dbms_datapump.ku$_status_wip,-1,job_state,sts);
  js := sts.job_status;

-- If the percentage done changed, display the new value.
if js.percent_done != percent_done
then
  dbms_output.put_line('*** Job percent done = ' || to_char(js.percent_done));
  percent_done := js.percent_done;
end if;

-- If any work-in-progress (WIP) or error messages were received for the job, display them.
if (bitand(sts.mask,dbms_datapump.ku$_status_wip) != 0)
then
  le := sts.wip;
else
  if (bitand(sts.mask,dbms_datapump.ku$_status_job_error) != 0)
  then
    le := sts.error;
  else
    le := null;
  end if;
end if;
if le is not null
then
  ind := le.FIRST;
  while ind is not null loop
    dbms_output.put_line(le(ind).LogText);
    ind := le.NEXT(ind);
  end loop;
end if;
  end loop;

  -- Indicate that the job finished and detach from it.
  dbms_output.put_line('Job has completed');
  dbms_output.put_line('Final job state = ' || job_state);
  dbms_datapump.detach(h1);
END;
/

出力されるメッセージはこちらです。

PL/SQL procedure successfully completed.

本当にうまくいったのか少し疑いたくなりますが、バケットにオブジェクトがあるのか確認すれば一目瞭然です。
指定したダンプファイルがバケットに格納されていました。
image.png

エクスポート時の詳細なログも確認することはできます。

SQL> SELECT * FROM DBMS_CLOUD.LIST_FILES('DATA_PUMP_DIR');

OBJECT_NAME            BYTES CHECKSUM      CREATED                                         LAST_MODIFIED
----------------- ---------- ------------- ----------------------------------------------- ----------------------------------------------
hr_app_exp.log          1778               05-NOV-25 10.24.23.000000 AM +00:00             05-NOV-25 10.31.14.000000 AM +00:00

(2-4) DBMS_DATAPUMPパッケージを利用したインポート

次はADB2で実行します。
先ほどのエクスポートによって生成されたダンプファイルを指定して、ADB2にインポートします。

DECLARE
ind NUMBER;  -- Loop index
h1 NUMBER;  -- Data Pump job handle
percent_done NUMBER;  -- Percentage of job complete
job_state VARCHAR2(30);  -- To keep track of job state
le ku$_LogEntry;  -- For WIP and error messages
js ku$_JobStatus;  -- The job status from get_status
jd ku$_JobDesc;  -- The job description from get_status
sts ku$_Status;  -- The status object returned by get_status
BEGIN

-- Create a (user-named) Data Pump job to do a "full" import (everything
-- in the dump file without filtering).
h1 := DBMS_DATAPUMP.OPEN('IMPORT','FULL',NULL,'SRCMIRROR_OCIGGLL_IMPORT');

-- Specify the single dump file for the job (using the handle just returned)
-- and directory object, which must already be defined and accessible
-- to the user running this procedure. This is the dump file created by
-- the export operation in the first example.

DBMS_DATAPUMP.ADD_FILE(h1,'https://***/o/SRC_OCIGGLL.dmp','EXPORT_CRED1',null,DBMS_DATAPUMP.KU$_FILE_TYPE_URIDUMP_FILE);
-- ★ここのオブジェクトURIの変更が必要

-- A metadata remap will map all schema objects from HR_APP to FIN_APP.
DBMS_DATAPUMP.METADATA_REMAP(h1,'REMAP_SCHEMA','HR_APP','FIN_APP');
-- ★REMAPを使用して、スキーマ名の変更をしました。

-- If a table already exists in the destination schema, skip it (leave
-- the preexisting table alone). This is the default, but it does not hurt
-- to specify it explicitly.
DBMS_DATAPUMP.SET_PARAMETER(h1,'TABLE_EXISTS_ACTION','SKIP');

-- Start the job. An exception is returned if something is not set up properly.
DBMS_DATAPUMP.START_JOB(h1);

-- The import job should now be running. In the following loop, the job is
-- monitored until it completes. In the meantime, progress information is
-- displayed. Note: this is identical to the export example.
percent_done := 0;
job_state := 'UNDEFINED';
while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
  dbms_datapump.get_status(h1,
    dbms_datapump.ku$_status_job_error +
    dbms_datapump.ku$_status_job_status +
    dbms_datapump.ku$_status_wip,-1,job_state,sts);
    js := sts.job_status;

  -- If the percentage done changed, display the new value.
  if js.percent_done != percent_done
  then
    dbms_output.put_line('*** Job percent done = ' ||
    to_char(js.percent_done));
    percent_done := js.percent_done;
  end if;

  -- If any work-in-progress (WIP) or Error messages were received for the job, display them.
  if (bitand(sts.mask,dbms_datapump.ku$_status_wip) != 0)
  then
    le := sts.wip;
  else
    if (bitand(sts.mask,dbms_datapump.ku$_status_job_error) != 0)
    then
      le := sts.error;
    else
      le := null;
    end if;
  end if;
  if le is not null
  then
    ind := le.FIRST;
    while ind is not null loop
      dbms_output.put_line(le(ind).LogText);
      ind := le.NEXT(ind);
    end loop;
  end if;
end loop;

-- Indicate that the job finished and gracefully detach from it.
dbms_output.put_line('Job has completed');
dbms_output.put_line('Final job state = ' || job_state);
dbms_datapump.detach(h1);
END;
/

出力されるメッセージは今回もこちらです。

PL/SQL procedure successfully completed.

PL/SQL内のREMAP部分でHR_APPスキーマのオブジェクトとしてエクスポートしたものをFIN_APPスキーマオブジェクトにリマップしたので、今回はFIN_APPとしてログインして確認します。

SQL> SELECT * FROM EMPLOYEES;

    EMP_ID NAME            DEPARTMENT           SALARY
---------- --------------- ---------------- ----------
         1 Alice           HR                     5000
         2 Bob             HR                     5200

こちらでも問題なく表示されました!
DBMS_DATAPUMPパッケージを利用する方法でも、問題なくオブジェクトのエクスポート・インポートができることを確認できました。

まとめ

今回はcompute経由でData Pumpの利用またはDATA_PUMPパッケージによるエクスポートとインポートを実施することで、ADB1にある特定のスキーマをADB2に移行することができました。
バックアップの際はエクスポートの手順でダンプファイルを取得しておいて、リストアする際にインポートの手順を実施することで特定のスキーマのみを過去の時点に戻すことができます。
その際には、computeがない環境でもDATA_PUMPパッケージで実行することができます。

5
2
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
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?