[OCI] PL/SQL SDKを使ってAutonomous Databaseのストレージサイズを使用率に応じてスケールアップ/スケールダウンしてみた

# はじめに

PL/SQL SDKでなにか実用的なことができないかと思い、接続しているAutonomous Databaseのストレージ使用率を取得して、ストレージの使用率が一定以上の場合はストレージをスケールアップ、使用率が一定以下の場合はストレージをスケールダウンする
PL/SQLプログラムを作成してみました。

※こちらの内容を参考にしてトラブルが発生しても一切責任は負いませんので、参考にされる際はくれぐれもご自身でしっかり検証してから、自己責任でお願いします。

# 処理の流れ
今回作成したプログラムは、ざっくり以下のような流れとなっています。

こちらの例では、ストレージ使用率が90%を超えている場合に自動で1TBスケールアップし、30%を下回っている場合に自動で1TBスケールダウンするようになっています。

1. ADBの現在のストレージサイズ（設定値）をPL/SQL SDKで取得します。
2. ADBの現在のストレージ使用量をSQLで取得します。
3. ストレージサイズとストレージ使用量から、ストレージ使用率を算出します。
4. ストレージ使用率が90%を超えている場合は、スケールアップ後のストレージサイズに現在のストレージサイズ+1TBをセットし、スケールアップを実行します。
5. 現在のストレージサイズが2TB以上かつストレージ使用率が30%を下まわる場合は、スケールダウン後のストレージサイズに現在のストレージサイズ-1TBをセットし、スケールダウンを実行します。
6. 上記4、5に該当しない場合は、そのまま処理を終了します。

# 作成したPL/SQLプログラム

作成した実際のPL/SQLプログラムは以下のようになります。
少し長いですが、あまり難しいことはしていません。

なお、事前に以下のものを用意しておく必要があります。
・Autonomous DatabaseのOCID
・Autonomous Databaseが存在するリージョンの識別子（ap-tokyo-1、ap-osaka-1など）
・Pl/SQL SDKのためのクレデンシャル（資格証明）

クレデンシャル（資格証明）の作成方法などは、こちらの記事を参考にしてください。

[[OCI] Autonomous DatabaseでOracle Cloud Infrastructure SDK for PL/SQL a.k.a. PL/SQL SDKを使ってみた](https://qiita.com/500InternalServerError/items/b7aba5d96c6c7b5e186b)

```
set serveroutput on
DECLARE
  --必要な変数、配列の宣言
  current_capacity_gb NUMBER;
  response_body_g  dbms_cloud_oci_db_database_autonomous_database_t;
  response_g       dbms_cloud_oci_db_database_get_autonomous_database_response_t;

  current_data_storage_size_in_t_bs NUMBER;
  current_gb NUMBER;
  current_usage_rate NUMBER;
  change_flg NUMBER;

  new_data_storage_size_in_t_bs NUMBER;
  autonomous_database_details     dbms_cloud_oci_db_database_update_autonomous_database_details_t;
  response_body_u  dbms_cloud_oci_db_database_autonomous_database_t;
  response_u       dbms_cloud_oci_db_database_update_autonomous_database_response_t;
  json_obj       json_object_t;
  l_keys         json_key_list;

BEGIN

  -- ADBの現在のストレージサイズ（TB）を取得
  response_g := DBMS_CLOUD_OCI_DB_DATABASE.get_autonomous_database (
  autonomous_database_id => 'ocid1.autonomousdatabase.oc1.ap-tokyo-1.XXXXXXXXXXXXXXXXXXXXXXXX',
  region => 'ap-tokyo-1', 
  credential_name => 'MY_SDK_CRED'
  );

  response_body_g := response_g.response_body;
  current_data_storage_size_in_t_bs := response_body_g.data_storage_size_in_t_bs;

  -- 現在のストレージサイズを表示
  dbms_output.put_line('Current Storage Size(TB):'||current_data_storage_size_in_t_bs);

  -- 現在のストレージサイズをTBからGBに  
  current_capacity_gb := current_data_storage_size_in_t_bs * 1024;

  -- 現在のストレージ使用量（GB）を取得
  SELECT SUM(bytes/1024/1024/1024) INTO current_GB FROM dba_data_files
  WHERE tablespace_name != 'SAMPLESCHEMA';
 
  -- 現在のストレージ利用率を計算 
  current_usage_rate := current_gb / current_capacity_gb;

  -- 現在のストレージ利用率を計表示
  dbms_output.put_line('Current Usage Rate:'||current_usage_rate/100);

  IF (current_usage_rate > 0.9) THEN
    -- ストレージ使用率が90%以上の場合は、変更後のストレージサイズを現在のストレージサイズに1TB追加し、変更フラグを1に
    new_data_storage_size_in_t_bs := current_data_storage_size_in_t_bs + 1;
    change_flg := 1;
  ELSIF (current_usage_rate < 0.3) AND (current_data_storage_size_in_t_bs > 1) THEN
    -- 現在のストレージサイズが1TB以外かつストレージ使用率が30%以下の場合は、変更後のストレージサイズを現在のストレージサイズから1TB削減し、変更フラグを1に
    new_data_storage_size_in_t_bs := current_data_storage_size_in_t_bs - 1;
    change_flg := 1;
  ELSE
    -- それ以外の場合は変更フラグを0に
    change_flg :=0;
  END IF;
    
  IF (change_flg = 1) THEN
    -- 変更フラグが1の場合は、変更後のストレージサイズにスケールアップ/ダウン
    autonomous_database_details := dbms_cloud_oci_db_database_update_autonomous_database_details_t();
    autonomous_database_details.data_storage_size_in_t_bs := new_data_storage_size_in_t_bs;
 
    response_u := DBMS_CLOUD_OCI_DB_DATABASE.update_autonomous_database (
    autonomous_database_id => 'ocid1.autonomousdatabase.oc1.ap-tokyo-1.XXXXXXXXXXXXXXXXXXXXXXXX',
    update_autonomous_database_details => autonomous_database_details,
    region => 'ap-tokyo-1',
    credential_name => 'MY_SDK_CRED'
    );
 
    response_body_u := response_u.response_body;
    
    -- レスポンスヘッダの表示
    dbms_output.put_line('Headers: ' || CHR(10) ||'------------');
    json_obj := response_u.headers;
    l_keys := json_obj.get_keys;
    for i IN 1..l_keys.count loop
     dbms_output.put_line(l_keys(i)||':'||json_obj.get(l_keys(i)).to_string);
    end loop;
 
    -- レスポンスのステータスコードの表示
    dbms_output.put_line('Status Code: ' || CHR(10) || '------------' || CHR(10) || response_u.status_code);
    dbms_output.put_line(CHR(10));
 
    -- 変更後のストレージサイズの表示
    dbms_output.put_line('New Storage Size(TB):'||new_data_storage_size_in_t_bs);

  ELSE
    -- 変更しなかった場合はその旨を表示
    dbms_output.put_line('Nothing changed.');

  END IF;
  
END;
/
```

# 実行結果
ストレージサイズが2TBでほぼストレージを使用していないAutonomous Databaseで、こちらのPL/SQLを実行してみます。
![スクリーンショット 2020-10-30 9.00.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/09e5ebcc-1858-3c77-5365-aa7a4b949c52.png)

```
Current Storage Size(TB)2
Current Usage Rate.000018846690654754638671875
Headers: 
------------
Connection:"close"
Date:"Fri, 30 Oct 2020 00:00:49 GMT"
opc-request-id:"49U2EP5QAN/F7D38F761BD4C8737C75676D6550076D/36D08541A28D6C8F64F7
F9D263B6658B"
ETag:"27075e50"
opc-work-request-id:"ocid1.coreservicesworkrequest.oc1.ap-tokyo-1.abxhiljrkvqmw6
e5ayfg5h2j2ds2iuvlxd7evbghja62ib4xu5z66zey2nrq"
Content-Type:"application/json"
X-Content-Type-Options:"nosniff"
Content-Length:"3868"
Status Code: 
------------
200


New Storage Size(TB)1


PL/SQL procedure successfully completed.

Elapsed: 00:00:01.509
```
サービス・コンソールを確認します。
![スクリーンショット 2020-10-30 9.02.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/2c33c228-9481-984f-8193-90d8dff9fe62.png)
Autonomous Databaseのステータスが「スケーリング進行中」に変わりました。

その後しばらく待つと、
![スクリーンショット 2020-10-30 9.08.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/071257fa-8c5a-eeb0-bc07-b7c04f64d310.png)
Autonomous Databaseのステータスが「使用中」に変わり、ストレージが1TBになりました。
![スクリーンショット 2020-10-30 9.09.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/6ab1a1b4-105c-e99f-1532-d1b0b6ef4193.png)

次に、ストレージサイズが1TBでストレージをほぼ使い果しているAutonomous Databaseで、こちらのPL/SQLを実行してみます。
![スクリーンショット 2020-10-30 11.40.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/389b13da-0279-e167-620a-180e9d93c31e.png)

```
Current Storage Size(TB):1
Current Usage Rate:.01097519338130950927734375
Headers: 
------------
Connection:"close"
Date:"Fri, 30 Oct 2020 02:37:51 GMT"
opc-request-id:"4PDV4UL9H5/2FF73834CEFA48A2D35FFE70228EF57E/FB4C3D3829CED31DB849
C07FDCE22998"
ETag:"2bb3be4c"
opc-work-request-id:"ocid1.coreservicesworkrequest.oc1.ap-tokyo-1.abxhiljr6xhboa
qcuibjq5mqniv7rloqkpvr32fonspsxfezw5ehfxdxwfpa"
Content-Type:"application/json"
X-Content-Type-Options:"nosniff"
Content-Length:"3868"
Status Code: 
------------
200


New Storage Size(TB):2


PL/SQL procedure successfully completed.

Elapsed: 00:00:01.534
```

`
サービス・コンソールを確認します。
![スクリーンショット 2020-10-30 11.38.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/1af8c2f7-2fe4-9fec-0912-72c7e066bc85.png)

Autonomous Databaseのステータスが「スケーリング進行中」に変わりました。

その後しばらく待つと、
![スクリーンショット 2020-10-30 11.48.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/f41f6d1f-5ab0-7c69-06b7-be942e948321.png)
Autonomous Databaseのステータスが「使用中」に変わり、ストレージが2TBになりました。
![スクリーンショット 2020-10-30 11.49.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/784824/ef814def-34b0-70f4-570d-169eb4c6c3d0.png)


# まとめ

今回はPL/SQLブロックの形でSQL Developer Webから実行しましたが、こちらの内容をPL/SQLプロシージャ化し、DBMS_SCHEDULERのジョブとして登録して実行すれば、ストレージの擬似オートスケリングも可能かもしれませんね。

今回使用したファンクション、DBMS_CLOUD_OCI_DB_DATABASEに関しては、こちらのドキュメントに記載があります。
[Oracle Cloud Infrastructure Documentation : DBMS_CLOUD_OCI_DB_DATABASE Functions](https://docs.cloud.oracle.com/en-us/iaas/pl-sql-sdk/doc/dbms_cloud_oci_db_database.html)
また、今回使用したデータ型については、こちらのドキュメントに記載があります。
[Oracle Cloud Infrastructure Documentation : DBMS_CLOUD_OCI_DB_DATABASE Types](https://docs.cloud.oracle.com/en-us/iaas/pl-sql-sdk/doc/dbms_cloud_oci_db_database_t.html)

PL/SQL SDKでは本当にいろいろなことができますので、可能性は無限大だと思います。
皆さんも是非いろいろ試してみてはいかがでしょうか。