Autonomous Databaseの全てのリフレッシュ可能クローンを一括でリフレッシュするPL/SQLプロシージャの作成

# はじめに
Autonomous Databaseには、リフレッシュ操作によってソースとなるAutonomous Databaseの更新内容を反映することができるリフレッシュ可能クローンという便利な機能があります。

リフレッシュ操作は、手動でのリフレッシュだけでなく、リフレッシュ頻度を指定して自動で実行することもできます。

今回は、バッチ処理等によるデータの変更後、即座に全てのリフレッシュ可能クローンをリフレッシュしたいというケースに向けて、ソースとなるAutonomous Databaseに関連づけられている全てのリフレッシュ可能クローンのリフレッシュを行うPL/SQLプロシージャを作成してみました。

※こちらの記事の内容はあくまで個人の実験メモ的な内容のため、こちらの内容を利用した場合のトラブルには一切責任を負いません。
また、こちらの記事の内容を元にしたOracleサポートへの問い合わせはご遠慮ください。

# 1. 事前準備

今回検証する対象となる大阪リージョン（ap-osaka-1）にあるAutonomous Databaseには2つのリフレッシュ可能クローンがあり、1つは大阪リージョン（ap-osaka-1）、もう一つは東京リージョン（ap-tokyo-1）にあります。

![スクリーンショット 2025-02-27 17.10.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/35e04f0c-7dac-41e3-a3cb-059132878063.png)

また、今回の検証ではリソース・プリンシパルを使用しますので、あらかじめ適切な動的グループ、ポリシーを作成しておきます。
なお、Autonomous Databaseのリフレッシュ可能クローンのリフレッシュには「use autonomous-database」ポリシーが必要です。

リフレッシュ可能クローンのソースとなっているAutonomous Databaseにadminユーザとして接続します。
```
[oracle@oracle23ai ~]$ sqlplus admin/Demo#1Demo#1@atp23aitest

SQL*Plus: Release 23.0.0.0.0 - Production on Thu Feb 27 17:17:16 2025
Version 23.4.0.24.05

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

Last Successful login time: Thu Feb 27 2025 16:57:49 +09:00

Connected to:
Oracle Database 23ai Enterprise Edition Release 23.0.0.0.0 - Production
Version 23.7.0.25.02

SQL>
```
DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPALプロシージャを使用して、リソース・プリンシパルを有効化します。
```
SQL> EXEC DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPAL();

PL/SQL procedure successfully completed.

SQL>
```

# 2. 全てのリフレッシュ可能クローンをリフレッシュするPL/SQLプロシージャの作成
リフレッシュのカットオフ時刻のタイムスタンプをパラメータとして渡して実行すると、関連づけられている全てのリフレッシュ可能クローンをリフレッシュするPL/SQLプロシージャ「refresh_all_clones」を作成します。

なお。プロシージャ「refresh_all_clones」は、リフレッシュ可能クローンのソースとなっているAutonomous Databaseで作成、実行します。

```sql:refresh_all_clonesプロシージャ
CREATE OR REPLACE PROCEDURE refresh_all_clones( refresh_cut_off IN TIMESTAMP WITH TIME ZONE )
IS
    adb_region   VARCHAR2(200);
    adb_ocid     VARCHAR2(200);
    clone_ocid   VARCHAR2(200);
    clone_region VARCHAR2(200);

    list_refreshable_clone_res       dbms_cloud_oci_db_database_list_autonomous_database_refreshable_clones_response_t;
    list_refreshable_clone_res_body  dbms_cloud_oci_database_refreshable_clone_collection_t;

    manual_refresh_detail    dbms_cloud_oci_database_autonomous_database_manual_refresh_details_t := dbms_cloud_oci_database_autonomous_database_manual_refresh_details_t();
    manual_refresh_res       dbms_cloud_oci_db_database_autonomous_database_manual_refresh_response_t;
    manual_refresh_res_body  dbms_cloud_oci_database_autonomous_database_t;

BEGIN
-- 入力されたパラメータをリフレッシュのカットオフ日時としてセット
    manual_refresh_detail.time_refresh_cutoff := refresh_cut_off;

-- ソースADBのあるリージョン、ソースADBのOCIDを取得
    SELECT JSON_VALUE(cloud_identity, '$.REGION'), LOWER(JSON_VALUE(cloud_identity, '$.DATABASE_OCID')) INTO adb_region, adb_ocid FROM v$pdbs;
	  
    DBMS_OUTPUT.PUT_LINE('Source ADB OCID:'||adb_ocid);
    DBMS_OUTPUT.PUT_LINE('Source ADB Region:'||adb_region);
    DBMS_OUTPUT.PUT_LINE('Cut Off Timestamp: '||manual_refresh_detail.time_refresh_cutoff);
    DBMS_OUTPUT.PUT_LINE('-----------');

-- リフレッシュ可能クローンの一覧を取得
    list_refreshable_clone_res := DBMS_CLOUD_OCI_DB_DATABASE.LIST_AUTONOMOUS_DATABASE_REFRESHABLE_CLONES(
                                      autonomous_database_id => adb_ocid,
                                      region => adb_region,
                                      credential_name => 'OCI$RESOURCE_PRINCIPAL');

-- リフレッシュ可能クローンの数だけループ
    FOR i IN list_refreshable_clone_res.response_body.items.first..list_refreshable_clone_res.response_body.items.last LOOP
	
-- リフレッシュ可能クローンのOCIDとリージョンを取得 
	    clone_ocid   := list_refreshable_clone_res.response_body.items(i).id;
		clone_region := list_refreshable_clone_res.response_body.items(i).l_region;

        DBMS_OUTPUT.PUT_LINE('Refreshable Clone OCID: '||clone_ocid);
        DBMS_OUTPUT.PUT_LINE('Refreshable Clone Region: '||clone_region);
		
-- リフレッシュ可能クローンのリフレッシュを実行
        manual_refresh_res := DBMS_CLOUD_OCI_DB_DATABASE.AUTONOMOUS_DATABASE_MANUAL_REFRESH(
                                  autonomous_database_id => clone_ocid,
                                  region                 => clone_region,
                                  autonomous_database_manual_refresh_details => manual_refresh_detail,
                                  credential_name => 'OCI$RESOURCE_PRINCIPAL');
								  
        DBMS_OUTPUT.PUT_LINE('Status Code: '||manual_refresh_res.status_code);
        DBMS_OUTPUT.PUT_LINE('-----------');
    END LOOP;
END;
/
```

```
SQL> CREATE OR REPLACE PROCEDURE refresh_all_clones( refresh_cut_off IN TIMESTAMP WITH TIME ZONE )
  2  IS
  3      adb_region   VARCHAR2(200);
  4  	 adb_ocid     VARCHAR2(200);
  5  	 clone_ocid   VARCHAR2(200);
  6  	 clone_region VARCHAR2(200);
  7  
  8  	 list_refreshable_clone_res	  dbms_cloud_oci_db_database_list_autonomous_database_refreshable_clones_response_t;
  9  	 list_refreshable_clone_res_body  dbms_cloud_oci_database_refreshable_clone_collection_t;
 10  
 11  	 manual_refresh_detail	  dbms_cloud_oci_database_autonomous_database_manual_refresh_details_t := dbms_cloud_oci_database_autonomous_database_manual_refresh_details_t();
 12  	 manual_refresh_res	  dbms_cloud_oci_db_database_autonomous_database_manual_refresh_response_t;
 13  	 manual_refresh_res_body  dbms_cloud_oci_database_autonomous_database_t;
 14  
 15  BEGIN
 16  -- 入力されたパラメータをリフレッシュのカットオフ日時としてセット
 17  	 manual_refresh_detail.time_refresh_cutoff := refresh_cut_off;
 18  
 19  -- ソースADBのあるリージョン、ソースADBのOCIDを取得
 20  	 SELECT JSON_VALUE(cloud_identity, '$.REGION'), LOWER(JSON_VALUE(cloud_identity, '$.DATABASE_OCID')) INTO adb_region, adb_ocid FROM v$pdbs;
 21  
 22  	 DBMS_OUTPUT.PUT_LINE('Source ADB OCID:'||adb_ocid);
 23  	 DBMS_OUTPUT.PUT_LINE('Source ADB Region:'||adb_region);
 24  	 DBMS_OUTPUT.PUT_LINE('Cut Off Timestamp: '||manual_refresh_detail.time_refresh_cutoff);
 25  	 DBMS_OUTPUT.PUT_LINE('-----------');
 26  
 27  -- リフレッシュ可能クローンの一覧を取得
 28  	 list_refreshable_clone_res := DBMS_CLOUD_OCI_DB_DATABASE.LIST_AUTONOMOUS_DATABASE_REFRESHABLE_CLONES(
 29  					   autonomous_database_id => adb_ocid,
 30  					   region => adb_region,
 31  					   credential_name => 'OCI$RESOURCE_PRINCIPAL');
 32  
 33  -- リフレッシュ可能クローンの数だけループ
 34  	 FOR i IN list_refreshable_clone_res.response_body.items.first..list_refreshable_clone_res.response_body.items.last LOOP
 35  
 36  -- リフレッシュ可能クローンのOCIDとリージョンを取得
 37  		 clone_ocid   := list_refreshable_clone_res.response_body.items(i).id;
 38  		     clone_region := list_refreshable_clone_res.response_body.items(i).l_region;
 39  
 40  	     DBMS_OUTPUT.PUT_LINE('Refreshable Clone OCID: '||clone_ocid);
 41  	     DBMS_OUTPUT.PUT_LINE('Refreshable Clone Region: '||clone_region);
 42  
 43  -- リフレッシュ可能クローンのリフレッシュを実行
 44  	     manual_refresh_res := DBMS_CLOUD_OCI_DB_DATABASE.AUTONOMOUS_DATABASE_MANUAL_REFRESH(
 45  				       autonomous_database_id => clone_ocid,
 46  				       region		      => clone_region,
 47  				       autonomous_database_manual_refresh_details => manual_refresh_detail,
 48  				       credential_name => 'OCI$RESOURCE_PRINCIPAL');
 49  
 50  	     DBMS_OUTPUT.PUT_LINE('Status Code: '||manual_refresh_res.status_code);
 51  	     DBMS_OUTPUT.PUT_LINE('-----------');
 52  	 END LOOP;
 53  END;
 54  /

Procedure created.

SQL> 
```
PL/SQLプロシージャ「refresh_all_clones」が作成できました。

# 3. 作成したプロシージャを使用したリフレッシュの実行

以下のようなPL/SQLブロックで、2.で作成したPL/SQLプロシージャ「refresh_all_clones」を、現在時刻の5分前のタイプスタンプをカットオフ日時に指定して実行してみます。

```sql
set serveroutput on
set linesize 150
DECLARE
    cutoff TIMESTAMP WITH TIME ZONE;
BEGIN
-- 5分前のタイムスタンプを取得
    SELECT current_timestamp - (5/1440) INTO cutoff;
-- 5分前のタイムスタンプをリフレッシュのカットオフ日時として指定してrefresh_all_clonesプロシージャを実行
	refresh_all_clones(cutoff);
END;
/
```

実行結果は以下のようになりました。
```
SQL> set serveroutput on
SQL> set linesize 150
SQL> DECLARE
  2      cutoff TIMESTAMP WITH TIME ZONE;
  3  BEGIN
  4  -- 5分前のタイムスタンプを取得
  5      SELECT current_timestamp - (5/1440) INTO cutoff;
  6  -- 5分前のタイムスタンプをリフレッシュのカットオフ日時として指定してrefresh_all_clonesプロシージャを実行
  7  	refresh_all_clones(cutoff);
  8  END;
  9  /
Source ADB OCID:ocid1.autonomousdatabase.oc1.ap-osaka-1.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Source ADB Region:ap-osaka-1
Cut Off Timestamp: 27-FEB-25 05.12.25.000000 PM +09:00
-----------
Refreshable Clone OCID: ocid1.autonomousdatabase.oc1.ap-osaka-1.yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
Refreshable Clone Region: ap-osaka-1
Status Code: 200
-----------
Refreshable Clone OCID: ocid1.autonomousdatabase.oc1.ap-tokyo-1.zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
Refreshable Clone Region: ap-tokyo-1
Status Code: 200
-----------

PL/SQL procedure successfully completed.

SQL>
```

OCIコンソールでリフレッシュ可能クローンのリストを確認すると、全てのリフレッシュ可能クローンの状態が「更新中」になりました。

![スクリーンショット 2025-02-27 17.18.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/c0d2a13e-04cc-47e1-8118-21cbbbe9ec1a.png)

リフレッシュが完了すると、状態が「使用可能」に変わり、リフレッシュ・ポイントがrefresh_all_clonesプロシージャを実行する際に指定したカットオフ日時のタイプスタンプ（UTC）になっていることが確認できました。

![スクリーンショット 2025-02-27 17.20.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/4dd81ee1-f0fd-42b4-be21-1d902b1e5ac0.png)

# 参考情報
・[IAM Policies for Autonomous Database](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/autonomous-database-iam-policies.html#GUID-30D58C83-9D35-4804-949D-459DBBDB3B25)
・[Obtain Tenancy Details - Autonomous Database](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/autonomous-database-support-ocid.html)
・[DBMS_CLOUD_OCI_DB_DATABASE.LIST_AUTONOMOUS_DATABASE_REFRESHABLE_CLONESファンクション](https://docs.oracle.com/en-us/iaas/Content/pl-sql-sdk/doc/dbms_cloud_oci_db_database.html#ADSDK-GUID-924DE13C-952B-4E05-A94F-1311DD4B0F9F)
・[DBMS_CLOUD_OCI_DB_DATABASE.AUTONOMOUS_DATABASE_MANUAL_REFRESHファンクション](https://docs.oracle.com/en-us/iaas/Content/pl-sql-sdk/doc/dbms_cloud_oci_db_database.html#ADSDK-GUID-9DA5EAC2-114F-4161-81C3-B0BBB8968C70)