[OCI]データベースリンクを使用して、2つのAutunomous Databaseの間で直接テーブルをコピーしてみた

# はじめに

Autonomous Database間でテーブルをコピーする（例えば開発環境のAutonomous Databaseから本番環境のAutonomous Databaseにテーブルをコピーする）方法として、Autonomous DB間でデータベースリンクを設定してCTASでテーブルをコピーする手順を試してみました。

イメージはこちらの図のような感じです。
![スクリーンショット 2021-02-05 18.52.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/a105a982-6f56-fa9b-4d7e-4fd0b21152e3.png)


# 1. ターゲット（テーブルのコピー元）となるAutonomous Databaseのクライアント資格証明のダウンロード

DEV_ATPのサービス・コンソールからクライアント資格証明（zipファイル）をダウンロードします。

ダウンロードしたzipファイルを解凍すると、以下のようなファイルが確認できます。
![スクリーンショット 2021-02-05 13.26.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/919f8471-e322-9e5c-09a1-7845b7da676b.png)

今回の手順では、こちらのファイルのうち、
・cwallet.sso
・tnsnames.ora
の2つのファイルを使用します。

# 2. Object Storageへのウォレットファイルのアップロード
ウォレットファイルをアップロードするためのオブジェクト・ストレージ・バケット**dblink_wallet**を作成します。
![スクリーンショット 2021-02-05 13.27.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/e0377832-800d-fb97-096a-26014894577c.png)
バケット**dblink_wallet**が作成されました。
![スクリーンショット 2021-02-05 13.28.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/daefd1ba-d4b8-38b8-43fe-d8d3a2adabdd.png)
バケット名をクリックして、バケットの詳細画面に移動します。
![スクリーンショット 2021-02-05 13.28.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/a249b863-bbe6-a961-9cbc-e356aad8e87c.png)
オブジェクト欄の「アップロード」をクリックします。
「ファイルを選択」をクリックします。
![スクリーンショット 2021-02-05 13.28.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/10223d91-da1a-73fa-c57f-4bea8f733d15.png)
**cwallet.sso**を選択します。
![スクリーンショット 2021-02-05 13.28.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/add39d5b-f5ac-6283-500b-034e00234f11.png)
「アップロード」をクリックして、**cwallet.sso**をアップロードします。
![スクリーンショット 2021-02-05 13.29.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/1bfe5ec0-78d0-6dfd-8952-780de8fc1cab.png)
バケット**dblink_wallet**に**cwallet.sso**がアップロードされました。
![スクリーンショット 2021-02-05 13.29.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/d952a9c8-7a30-3328-1901-5f2020e74f2e.png)

# 3. 事前認証済リクエストの作成
Object Storageにアップロードしたcwallet.ssoにアクセスするための事前認証済リクエストを作成します。

リソース欄の「事前認証済リクエスト」をクリックします。
![スクリーンショット 2021-02-05 13.29.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/4a05c460-4c7d-80be-644c-6b4cbb673dd1.png)
「事前認証済リクエストの作成」をクリックします。
![スクリーンショット 2021-02-05 13.29.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/84c982de-104c-96bb-4b97-fe2dea387a0e.png)
事前認証済リクエスト・ターゲットは「オブジェクト」を選択し、オブジェクト名に**cwallet.sso**を入力して、「事前認証済リクエストの作成」をクリックします。
![スクリーンショット 2021-02-05 19.35.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/ce06c08a-4508-302f-b251-990a93908b5e.png)
事前認証済リクエストが作成され、詳細が表示されます。
事前認証済リクエストのURLをコピーします。
**※事前認証済みURLは、作成時に1度しか表示されないので注意してください。**
![スクリーンショット 2021-02-05 13.31.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/fdaae025-bec1-f157-e90d-34a968c8ba16.png)

# 4. ウォレットファイル格納用ディレクトリ・オブジェクトの作成
PROD_ATPのサービス・コンソールからSQL Developer Webにアクセスし、adminユーザでログインします。

Autonomous Database内にウォレットファイルを格納するためのディレクトリオブジェクトを作成します。

```
CREATE DIRECTORY dev_dblink_wallet_dir AS 'dev_dblink_wallet';
```

# 5.ウォレットファイルのディレクトリ・オブジェクトへのアップロード
DBMS_CLOUD.GET_OBJECTプロシージャを使用して、Object Storageにアップロードしたフォレットファイルを、4.で作成したディレクトリ・オブジェクトにコピーします。

DBMS_CLOUD.GET_OBJECTプロシージャの引数として、
・object_uriには、3.で作成した事前認証済リクエストのURLを
・directory_nameには4.で作成したディレクトリ・オブジェクトの名前を
それぞれ指定します。

```
BEGIN 
     DBMS_CLOUD.GET_OBJECT(
        object_uri => 'https://objectstorage.ap-tokyo-1.oraclecloud.com/p/XXXXXXXXXXXXXXXXXXXXXXX/n/XXXXXXX/b/dblink_wallet/o/cwallet.sso',
        directory_name => DEV_'DBLINK_WALLET_DIR'); 
END;
/
```

# 6.データベースリンクのためのクレデンシャルの作成
データベース・リンク経由でターゲットのAutonomous Databaseにアクセスするためのクレデンシャルを、DBMS_CLOUD.CREATE_CREDENTIALプロシージャを使用して作成します。

DBMS_CLOUD.CREATE_CREDENTIALプロシージャの引数として、
・usernameには接続先のAutunomous Databaseのユーザ名
・passwordにはそのユーザのパスワード
をそれぞれ指定します。

今回はadminユーザのcustomerテーブルをコピーするので、DBMS_CLOUD.CREATE_CREDENTIALプロシージャの引数として、
・usernameにadmin
・passwordにadminユーザのパスワード
をそれぞれ指定します。

```
BEGIN
  DBMS_CLOUD.CREATE_CREDENTIAL(
    credential_name => 'DEV_DBLINK_CRED',
    username => 'ADMIN',
    password => 'Demo#1Demo#1'
  );
END;
/
```

# 7.データベースリンクの作成
DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINKプロシージャを使用して、DBリンクを作成します。

DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINKプロシージャの一部の引数は、DEV_ATPの資格証明内にあるtnsnames.oraファイルから情報を取得して設定します。

以下は、ダウンロードしたDEV_ATPの資格証明内のtnsnames.oraの内容の抜粋です。

```
devatp_high = 
(
 description=
  (retry_count=20)
  (retry_delay=3)
  (address=
   (protocol=tcps)
   (port=1522)
   (host=adb.ap-tokyo-1.oraclecloud.com)
  )
  (connect_data=
   (service_name=XXXXXXXX_devatp_high.adb.oraclecloud.com)
  )
  (security=
   (ssl_server_cert_dn="CN=adb.ap-tokyo-1.oraclecloud.com,OU=Oracle ADB TOKYO,O=Oracle Corporation,L=Redwood City,ST=California,C=US")
 )
)
```

DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINKプロシージャの引数として
・hostnameにtnsnames.oraの中のhostの値を
・portにtnsnames.oraの中のportの値を
・service_nameにtnsnames.oraの中のservice_nameの値を
・ssl_server_cert_dnにtnsnames.oraの中のssl_server_cert_dnの値を
それぞれ設定します。

また、DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINKプロシージャの引数として
・credential_nameに6.で作成したクレデンシャル名を
・directory_nameに4.で作成したディレクトリ・オブジェクト名を
それぞれ設定します。

それでは、DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINKプロシージャを使用してデータベース・リンクを作成します。

```
BEGIN
     DBMS_CLOUD_ADMIN.CREATE_DATABASE_LINK(
          db_link_name => 'DEV_DBLINK', 
          hostname => 'adb.ap-tokyo-1.oraclecloud.com', 
          port => '1522',
          service_name => 'XXXXXXXX_devatp_high.adb.oraclecloud.com',
          ssl_server_cert_dn => 'CN=adb.ap-tokyo-1.oraclecloud.com,OU=Oracle ADB TOKYO,O=Oracle Corporation,L=Redwood City,ST=California,C=US',
          credential_name => 'DEV_DBLINK_CRED',
          directory_name => 'DEV_DBLINK_WALLET_DIR');
END;
/
```

データベースリンクが作成できたので、DEV_ATP内のcustomerテーブルをCREATE TABLE AS SELECTでPROD_ATPにコピーします。

```
CREATE TABLE customer
AS
SELECT * FROM CUSTOMER@dev_dblink

Table CUSTOMER created.

Elapsed: 00:00:05.660
```
customerテーブルがコピーされたかを確認してみます。

```
SELECT COUNT(*) FROM CUSTOMER;

COUNT(*) 
-------- 
 1000000 

Elapsed: 00:00:00.122
1行が選択されました。
```
DEV_ATPにあったcustomerテーブルが100万件のデータと一緒にコピーされていることが確認できました。

# まとめ
データベース・リンクを作成して、Autonomous Database間で直接テーブルをコピーできることが確認できました。
めでたし、めでたし。