[OCI]Autonomous Databaseに追加されたCloud Linksによるデータ共有を試してみた

#はじめに
Autonomous Databaseにクラウドベースの方法でAutonomous Database間のデータ共有を行うことができるCloud Linksの機能が追加されました。
Cloud Linksを使用すると、Autonomous Database間のネットワーク的な接続を設定することなく、データを共有するスコープとしてリージョン、テナント、コンパートメント、特定のAutonomous Databaseを指定してデータの読み取り専用リモートアクセスを提供することができます。

今回は、こちらの構成図のように同じテナント内にある2つのAutonomous Database間でのCloud Linksによるデータ共有を試してみました。
![スクリーンショット 2023-03-31 10.33.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/a19577df-a432-e450-b2bd-b8a6f613a030.png)

# 1. ユーザ作成と権限の付与

SQL*Plusからadminユーザとしてtestadb1に接続します。
```
[opc@client ~]$ sqlplus admin/Demo#1Demo#1@testadb1

SQL*Plus: Release 21.0.0.0.0 - Production on 木 3月 30 08:16:42 2023
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: 木 3月  30 2023 08:16:24 +00:00


Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0
に接続されました。
SQL>
```
Cloud Linksの登録ユーザ「cloud_links_register_user」を作成し、必要な権限を付与します。
```
SQL> CREATE USER cloud_links_register_user IDENTIFIED BY Demo#1Demo#1;

ユーザーが作成されました。

SQL> GRANT CONNECT, RESOURCE, UNLIMITED TABLESPACE TO cloud_links_register_user;

権限付与が成功しました。

SQL> GRANT EXECUTE ON DBMS_CLOUD_LINK TO cloud_links_register_user;

権限付与が成功しました。

SQL> 
```
DBMS_CLOUD_LINK_ADMIN.GRANT_REGISTERプロシージャを使用して、cloud_links_register_userユーザに、Cloud Linksにオブジェクトを登録するための権限を付与します。

scopeには、ユーザがどのスコープにアクセスできるようにするかを以下の値のいずれかで指定します。
・MY$REGION：ユーザは、データセットを登録したAutonomous Databseと同じリージョン内の別のテナンシにもリモートデータアクセスを許可することができます。
・MY$TENANCY：ユーザは、データセットを登録したAutonomous Databseと同じテナント内の全てのリソースにリモートデータアクセスを許可することができます。
・MY$COMPARTMENT：ユーザは、データセットを登録したAutonomous Databseと同じコンパートメント内の全てのリソースにリモートデータアクセスを許可することができます。
```
SQL> BEGIN
  2  DBMS_CLOUD_LINK_ADMIN.GRANT_REGISTER(
  3     username => 'CLOUD_LINKS_REGISTER_USER', -- ユーザ名
  4     scope    => 'MY$TENANCY'); -- スコープ
  5  END;
  6  /

PL/SQLプロシージャが正常に完了しました。

SQL>
```
次にCloud Linksの参照ユーザ「cloud_links_access_user」を作成し、必要な権限を付与します。
```
SQL> CREATE USER cloud_links_access_user IDENTIFIED BY Demo#1Demo#1;

ユーザーが作成されました。

SQL> GRANT CONNECT, RESOURCE, UNLIMITED TABLESPACE TO cloud_links_access_user;

権限付与が成功しました。

SQL> GRANT EXECUTE ON DBMS_CLOUD_LINK TO cloud_links_access_user;

権限付与が成功しました。

SQL> 
```
DBMS_CLOUD_LINK_ADMIN.GRANT_READプロシージャを使用して、cloud_links_access_userユーザに、Cloud Linksに登録されているデータセットを参照するための権限を付与します。
```
SQL> EXEC DBMS_CLOUD_LINK_ADMIN.GRANT_READ('CLOUD_LINKS_ACCESS_USER');

PL/SQLプロシージャが正常に完了しました。

SQL>
```
SQL*Plusを終了します。
```
SQL> exit
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0との接続が切断されました。
[opc@client ~]$
```

# 2. 検証用テープルの作成とCloud Linksへのテーブルの登録

SQL*Plusからcloud_links_register_userユーザとしてtestadb1に接続します。
```
[opc@client ~]$ sqlplus cloud_links_register_user/Demo#1Demo#1@testadb1

SQL*Plus: Release 21.0.0.0.0 - Production on 木 3月 30 08:20:38 2023
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.



Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0
に接続されました。
SQL>
```
検証用の表「dept」を作成し、データをINSERTします。
```
SQL> CREATE TABLE dept (
  2    deptno NUMBER(2) CONSTRAINT PK_DEPT PRIMARY KEY,
  3    dname VARCHAR2(14),
  4    loc VARCHAR2(13)
  5  );

表が作成されました。

SQL> INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK');

1行が作成されました。

SQL> INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');

1行が作成されました。

SQL> INSERT INTO DEPT VALUES (30,'SALES','CHICAGO');

1行が作成されました。

SQL> INSERT INTO DEPT VALUES (40,'OPERATIONS','BOSTON');

1行が作成されました。

SQL> COMMIT;

コミットが完了しました。

SQL> 
```
dept表の内容を確認します。
```
SQL> SELECT * FROM dept;

    DEPTNO DNAME	      LOC
---------- -------------- -------------
	    10 ACCOUNTING	  NEW YORK
	    20 RESEARCH	      DALLAS
	    30 SALES	      CHICAGO
	    40 OPERATIONS	  BOSTON

SQL>
```
DBMS_CLOUD_LINK.REGISTERプロシージャを使用して、dept表をCloud Linksのネームスペース「COMPANY」に「DEPARTMENT」という名前のデータセットとして登録し、テナント内のデータベースにアクセスを許可します。

scopeには、登録するデータセットをどの範囲に共有するかを以下の値のいずれかで指定します。
複数の値をカンマ区切りで指定することも可能です。
・Database OCID：OCIDで指定した特定のAutonomous Databaseにデータセットへのアクセスを許可
・Compartment OCID：OCIDで指定した特定のコンパートメント内のデータベースにデータセットへのアクセスを許可
・Tenancy OCID：OCIDで指定した特定のテナント内のデータベースにデータセットへのアクセスを許可
・MY$REGION：データセットの所有者と同じリージョン内のデータベースにデータセットへのアクセスを許可
・MY$TENANCY：データセットの所有者と同じテナント内のデータベースにデータセットへのアクセスを許可
・MY$COMPARTMENT：データセットの所有者と同じコンパートメント内のデータベースにデータセットへのアクセスを許可
```
SQL> BEGIN
  2    DBMS_CLOUD_LINK.REGISTER(
  3      schema_name    => 'CLOUD_LINKS_REGISTER_USER', -- ユーザ名
  4      schema_object  => 'DEPT', -- オブジェクト名
  5      namespace      => 'COMPANY', -- データセットを登録するネームスペース
  6      name           => 'DEPARTMENT', -- データセット名
  7      description    => 'Department information.', -- データセットの説明
  8      scope          => 'MY$TENANCY' -- データセットを共有するスコープ
  9    );
 10  END;
 11  /

PL/SQLプロシージャが正常に完了しました。

SQL>
```
SQL*Plusを終了します。
```
SQL> exit
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0との接続が切断されました。
[opc@client ~]$
```

# 3. Cloud Linksに登録されているデータセットの参照

SQL*Plusからcloud_links_access_userユーザとしてtestadb1に接続します。
```
[opc@client ~]$ sqlplus cloud_links_access_user/Demo#1Demo#1@testadb1

SQL*Plus: Release 21.0.0.0.0 - Production on 木 3月 30 08:26:19 2023
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.



Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0
に接続されました。
SQL> 
```
DBMS_CLOUD_LINK.FINDプロシージャを使用して、 "DEPARTMENT"を含むデータセットを確認します。

```
SQL> set serveroutput on
SQL> DECLARE
  2    result CLOB DEFAULT NULL;
  3  BEGIN
  4    DBMS_CLOUD_LINK.FIND('DEPARTMENT', result);
  5    DBMS_OUTPUT.PUT_LINE(result);
  6  END;
  7  /
[{"name":"DEPARTMENT","namespace":"COMPANY","description":"Department
information."}]

PL/SQLプロシージャが正常に完了しました。

SQL>
```
ネームスペースCOMPANY内にDEPARTMENTという名前のデータセットが登録されていることがわかります。

SELECT文でデータセットの内容を確認します。
Cloud Linksに登録されているデータセットを参照するには、
**ネームスペース名.データセット名＠&#xFFF0;cloud$link**
をFROM句に指定します。
```
SQL> SELECT * FROM COMPANY.DEPARTMENT@cloud$link;

    DEPTNO DNAME	      LOC
---------- -------------- -------------
	    10 ACCOUNTING	  NEW YORK
	    20 RESEARCH	      DALLAS
	    30 SALES	      CHICAGO
	    40 OPERATIONS	  BOSTON

SQL>
```
Cloud Linksを使用して、データを参照することができました。

SQL*Plusを終了します。
```
SQL> exit
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0との接続が切断されました。
[opc@client ~]$
```


# 4. 異なるAutonomous DatabaseからCloud Linksに登録されているデータセットを参照
データセットの登録を行なったAutonomous Databaseとは別のAutonomous Databaseから、Cloud Linksを使用してデータを参照してみます。

SQL*Plusからadminユーザとしてtestadb2に接続します。
```
[opc@client ~]$ sqlplus admin/Demo#1Demo#1@testadb2

SQL*Plus: Release 21.0.0.0.0 - Production on 木 3月 30 08:31:44 2023
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

最終正常ログイン時間: 木 3月  30 2023 08:16:29 +00:00


Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0
に接続されました。
SQL> 
```
Cloud Linksにアクセスするためのユーザ「cloud_links_remote_access_user」を作成し、必要な権限を付与します。
```
SQL> CREATE USER cloud_links_remote_access_user IDENTIFIED BY Demo#1Demo#1;

ユーザーが作成されました。

SQL> GRANT CONNECT, RESOURCE, UNLIMITED TABLESPACE TO cloud_links_remote_access_user;

権限付与が成功しました。

SQL> GRANT EXECUTE ON DBMS_CLOUD_LINK TO cloud_links_remote_access_user;

権限付与が成功しました。

SQL> 
```
先程と同様に、DBMS_CLOUD_LINK_ADMIN.GRANT_READプロシージャを使用して、cloud_links_remote_access_userユーザに、Cloud Linksに登録されているデータセットを参照するための権限を付与します。
```
SQL> EXEC DBMS_CLOUD_LINK_ADMIN.GRANT_READ('CLOUD_LINKS_REMOTE_ACCESS_USER');

PL/SQLプロシージャが正常に完了しました。

SQL>
```
SQL*Plusを終了します。
```
SQL> exit
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0との接続が切断されました。
[opc@client ~]$
```
SQL*Plusからcloud_links_remote_access_userユーザとしてtestadb2に接続します。
```
opc@client ~]$ sqlplus cloud_links_remote_access_user/Demo#1Demo#1@testadb2

SQL*Plus: Release 21.0.0.0.0 - Production on 木 3月 30 08:33:08 2023
Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.



Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.19.0.1.0
に接続されました。
SQL> 
```
DBMS_CLOUD_LINK.FINDプロシージャを使用して、 "DEPARTMENT"を含むデータセットを確認します。
```
SQL> set serveroutput on
SQL> DECLARE
  2    result CLOB DEFAULT NULL;
  3  BEGIN
  4    DBMS_CLOUD_LINK.FIND('DEPARTMENT', result);
  5    DBMS_OUTPUT.PUT_LINE(result);
  6  END;
  7  /
[{"name":"DEPARTMENT","namespace":"COMPANY","description":"Department
information."}]

PL/SQLプロシージャが正常に完了しました。

SQL>
```
データセットを登録したAutonomous Databaseとは別のAutonomous Databaseからも、データセットDEPARTMENTが確認できました。

先程と同様に、データセットの内容を確認します。

```
SQL> SELECT * FROM COMPANY.DEPARTMENT@cloud$link;

    DEPTNO DNAME	      LOC
---------- -------------- -------------
	    10 ACCOUNTING	  NEW YORK
	    20 RESEARCH	      DALLAS
	    30 SALES	      CHICAGO
	    40 OPERATIONS	  BOSTON

SQL>
```
データセットを登録したAutonomous Databaseとは別のAutonomous Databaseからも、データセットのデータが参照できることが確認できました。

# 注意点
マニュアルによると、以下のような点に注意が必要です。
・Cloud Linksによるデータ共有へのアクセスは同じリージョン内でのみ可能
・Cloud Linksでのリモートアクセスで使用されるサービスはLOWで変更は不可
・Cloud Linksのインターフェース（DBMS_CLOUD_LINKパッケージ、DBMS_CLOUD_LINK_ADMINパッケージ）は大文字小文字を区別する
・Cloud Linksのインターフェース（DBMS_CLOUD_LINKパッケージ、DBMS_CLOUD_LINK_ADMINパッケージ）では、ユーザ名、テーブル名等のDBオブジェクトの名前は大文字で指定する必要がある
・データセットの登録時にネームスペース名、データセット名を小文字で入力した場合は、SQLからアクセスする場合にダブルクオートで囲む必要がある
　例：
```
SELECT * FROM "company"."department"@cloud$link;
```

# 参考情報
・[Using Cloud Links for Read Only Data Access on Autonomous Database](https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/autonomous-cloud-links.html#GUID-918B48B3-0D1C-4CD5-AA04-380C043573B9)