【OCI クラウド移行ガイド】 Amazon RDS for PostgreSQL を OCI Database with PostgreSQLへ移行してみた

# OCIクラウド移行ガイドとは

オンプレミスやAWSなど、複数のプラットフォームからOracle Cloud Infrastructureへの移行プロジェクトに取り組んでいるクラウドエンジニア（@araidon,@kazunishi,@yama6）による、OCI移行手順をまとめたシリーズ記事です。
各回、サンプルワークロードから対象サービスを取り上げ、移行手順をガイドいたします。
まとめ記事は以下になります。

https://qiita.com/yama6/items/b197c0fe3ec75eb02637

# 移行するサービス：Amazon RDS for PostgreSQL

今回、移行対象とするのはAmazon RDS for PostgreSQLです。
PostgreSQLクライアントアプリケーションである、pg_dumpと、pg_restoreを用いて、
RDS for PostgreSQLのDBをOCI Database with PostgreSQLに移行してみます。

# 移行イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276568/8d44b443-7c15-96c5-a61f-dfbd3d1cba16.png)


# 前提条件
- AWSとOCI、それぞれに接続するための踏み台・作業用サーバがパブリックサブネット上に構築されていること。
- OCI Database with PostgreSQLが構築済みなこと。

OCI Database with PostgreSQLは2023/11/15にGAしたばかりのサービスです。
以下の構築してみた記事を参考にしていただければと思います。

https://qiita.com/dingtianhongjie/items/8547e156fb8e4528733e



## 動作検証用データベース
本ブログでは、以下サイトのdvdrental DBを利用して移行前後のテーブル内容を確認します。

https://www.postgresqltutorial.com/postgresql-getting-started/postgresql-sample-database/

## Amazon RDS for PostgreSQLでの動作確認結果
<details><summary>動作確認結果（長文のため折りたたみ）</summary><div>

```
dvdrental=> \dt;
             List of relations
 Schema |     Name      | Type  |  Owner   
--------+---------------+-------+----------
 public | actor         | table | postgres
 public | address       | table | postgres
 public | category      | table | postgres
 public | city          | table | postgres
 public | country       | table | postgres
 public | customer      | table | postgres
 public | film          | table | postgres
 public | film_actor    | table | postgres
 public | film_category | table | postgres
 public | inventory     | table | postgres
 public | language      | table | postgres
 public | payment       | table | postgres
 public | rental        | table | postgres
 public | staff         | table | postgres
 public | store         | table | postgres
(15 rows)

dvdrental=> select * from actor limit 20;
 actor_id | first_name |  last_name   |      last_update       
----------+------------+--------------+------------------------
        1 | Penelope   | Guiness      | 2013-05-26 14:47:57.62
        2 | Nick       | Wahlberg     | 2013-05-26 14:47:57.62
        3 | Ed         | Chase        | 2013-05-26 14:47:57.62
        4 | Jennifer   | Davis        | 2013-05-26 14:47:57.62
        5 | Johnny     | Lollobrigida | 2013-05-26 14:47:57.62
        6 | Bette      | Nicholson    | 2013-05-26 14:47:57.62
        7 | Grace      | Mostel       | 2013-05-26 14:47:57.62
        8 | Matthew    | Johansson    | 2013-05-26 14:47:57.62
        9 | Joe        | Swank        | 2013-05-26 14:47:57.62
       10 | Christian  | Gable        | 2013-05-26 14:47:57.62
       11 | Zero       | Cage         | 2013-05-26 14:47:57.62
       12 | Karl       | Berry        | 2013-05-26 14:47:57.62
       13 | Uma        | Wood         | 2013-05-26 14:47:57.62
       14 | Vivien     | Bergen       | 2013-05-26 14:47:57.62
       15 | Cuba       | Olivier      | 2013-05-26 14:47:57.62
       16 | Fred       | Costner      | 2013-05-26 14:47:57.62
       17 | Helen      | Voight       | 2013-05-26 14:47:57.62
       18 | Dan        | Torn         | 2013-05-26 14:47:57.62
       19 | Bob        | Fawcett      | 2013-05-26 14:47:57.62
       20 | Lucille    | Tracy        | 2013-05-26 14:47:57.62
(20 rows)

dvdrental=> select count(*) from actor;
 count 
-------
   200
(1 row)

dvdrental=> 
dvdrental=> select * from film_actor limit 10;
 actor_id | film_id |     last_update     
----------+---------+---------------------
        1 |       1 | 2006-02-15 10:05:03
        1 |      23 | 2006-02-15 10:05:03
        1 |      25 | 2006-02-15 10:05:03
        1 |     106 | 2006-02-15 10:05:03
        1 |     140 | 2006-02-15 10:05:03
        1 |     166 | 2006-02-15 10:05:03
        1 |     277 | 2006-02-15 10:05:03
        1 |     361 | 2006-02-15 10:05:03
        1 |     438 | 2006-02-15 10:05:03
        1 |     499 | 2006-02-15 10:05:03
(10 rows)

dvdrental=> select * from store limit 10;
 store_id | manager_staff_id | address_id |     last_update     
----------+------------------+------------+---------------------
        1 |                1 |          1 | 2006-02-15 09:57:12
        2 |                2 |          2 | 2006-02-15 09:57:12
(2 rows)

dvdrental=> select * from city limit 10;
 city_id |        city        | country_id |     last_update     
---------+--------------------+------------+---------------------
       1 | A Corua (La Corua) |         87 | 2006-02-15 09:45:25
       2 | Abha               |         82 | 2006-02-15 09:45:25
       3 | Abu Dhabi          |        101 | 2006-02-15 09:45:25
       4 | Acua               |         60 | 2006-02-15 09:45:25
       5 | Adana              |         97 | 2006-02-15 09:45:25
       6 | Addis Abeba        |         31 | 2006-02-15 09:45:25
       7 | Aden               |        107 | 2006-02-15 09:45:25
       8 | Adoni              |         44 | 2006-02-15 09:45:25
       9 | Ahmadnagar         |         44 | 2006-02-15 09:45:25
      10 | Akishima           |         50 | 2006-02-15 09:45:25
(10 rows)

```

</div></details>

# 移行フロー
1. AWSの作業用EC2に、PostgreSQLクライアントをインストール
1. pg_dump を利用してDatabaseのDumpファイルを作成
1. DumpファイルをOCIの作業用Computeに手動コピー
1. OCIの作業用Computeに、PostgreSQLクライアントをインストール
1. pg_restore を利用して、DatabaseのRestoreを実行

# 1. AWSの作業用EC2: PostgreSQLクライアントをインストール
:::note info
既にインストール済みの場合は手順2に進んでください。
:::

各種linuxに対応した手順でインストールを実施してください。
各種OSごとの手順は以下を参照してください。

https://www.postgresql.org/download/

（例）Ubuntuでの手順
```shell
$ sudo apt install -y postgresql-client

$ psql --version
psql (PostgreSQL) 14.9 (Ubuntu 14.9-0ubuntu0.22.04.1)
```

# 2. AWSの作業用EC2: pg_dump を利用してDatabaseのDumpファイルを作成
以下のコマンドでDumpファイルを作成します。
```shell
$ pg_dump -h rds-postgresql.xxxxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -U postgres -O -x --format=t --file=fromaws_dvdrental.tar dvdrental
Password: 
$

$ ls -l ./fromaws_dvdrental.tar 
-rw-rw-r-- 1 ubuntu ubuntu 2831872 Nov 15 14:22 ./fromaws_dvdrental.tar
$ 
```

| 項目 | 説明 |
|:-:|:-|
| -h | ホスト名を指定。RDS for PostgreSQLのエンドポイントを指定します。  |
| -U | 接続ユーザー名を指定。対象DBの読み取り権限が必要です。  |
| -O | オブジェクトの所有権を出力しないオプション。別のDBにリストアするためにはこのオプションを付ける必要があります。  |
| -x | アクセス権限（grant/revokeコマンド）のダンプを抑制します。 |
| --format=t | pg_restoreへの入力に適したtar形式のアーカイブを出力します。 |
| --file= | 出力を指定のファイルに送ります。   |

項目の詳細は以下公式サイトを参照してください。

https://www.postgresql.jp/document/15/html/app-pgdump.html



# 3. DumpファイルをOCIの作業用Computeに手動コピー
作成したファイルを任意の方法でコピーしてください。

# 4. OCIの作業用Compute:PostgreSQLクライアントをインストール
:::note info
既にインストール済みの場合は手順5に進んでください。
:::

各種linuxに対応した手順でインストールを実施してください。
各種OSごとの手順は以下を参照してください。

https://www.postgresql.org/download/

# 5. OCIの作業用Compute: pg_restore を利用して、DatabaseのRestoreを実行

## 5.1. リストア元DBの作成
リストアする前に、予めDatabaseを作成しておく必要があります。
DB名は、移行前と異なってもOKです。
以降の手順では、 __「oci_dvdrental」__ というDB名で作成してます。
```shell
$ psql -h 10.1.1.134 -U postgres -d postgres
Password for user postgres: 
psql (15.3, server 14.9)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.

postgres=> create database oci_dvdrental;
CREATE DATABASE

```

DBが作成されたことと、中身が空のことを確認。

```shell
postgres=> \l
                                                           List of databases
     Name      |     Owner     | Encoding |   Collate   |    Ctype    | ICU Locale | Locale Provider |        Access privileges        
---------------+---------------+----------+-------------+-------------+------------+-----------------+---------------------------------
 oci_dvdrental | postgres      | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | 
 postgres      | oci_superuser | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | 
 template0     | oci_superuser | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/oci_superuser               +
               |               |          |             |             |            |                 | oci_superuser=CTc/oci_superuser
 template1     | oci_superuser | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/oci_superuser               +
               |               |          |             |             |            |                 | oci_superuser=CTc/oci_superuser
(4 rows)

postgres=> \c oci_dvdrental;
psql (15.3, server 14.9)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
You are now connected to database "oci_dvdrental" as user "postgres".

oci_dvdrental=> \dt;
Did not find any relations.
oci_dvdrental=>
```

## 5.2. pg_restore を利用して、DatabaseのRestoreを実行

以下のコマンドで、リストアを実行
```shell
$ pg_restore -h 10.1.1.134 -U postgres -O -d oci_dvdrental ./fromaws_dvdrental.tar 
Password: 
$
```

| 項目 | 説明 |
|:-:|:-|
| -h | ホスト名を指定。OCI Database with PostgreSQLのエンドポイントを指定します。  |
| -U | 接続ユーザー名を指定します。|
| -O | オブジェクトの所有権を出力しないオプション。全てのオブジェクトの所有者がリストアしたユーザになります。  |
| -d | このデータベースに直接リストアします。 |

項目の詳細は以下公式サイトを参照してください。

https://www.postgresql.jp/document/15/html/app-pgrestore.html

# 動作確認
OCI Database with PostgreSQLのエンドポイントにログインし、動作確認をします。

<details><summary>動作確認結果（長文のため折りたたみ）</summary><div>

```
$ psql -h 10.1.1.134 -U postgres -d oci_dvdrental
Password for user postgres: 
psql (15.3, server 14.9)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.

oci_dvdrental=> 
oci_dvdrental=> \dt;
             List of relations
 Schema |     Name      | Type  |  Owner   
--------+---------------+-------+----------
 public | actor         | table | postgres
 public | address       | table | postgres
 public | category      | table | postgres
 public | city          | table | postgres
 public | country       | table | postgres
 public | customer      | table | postgres
 public | film          | table | postgres
 public | film_actor    | table | postgres
 public | film_category | table | postgres
 public | inventory     | table | postgres
 public | language      | table | postgres
 public | payment       | table | postgres
 public | rental        | table | postgres
 public | staff         | table | postgres
 public | store         | table | postgres
(15 rows)

oci_dvdrental=> select * from actor limit 20;
 actor_id | first_name |  last_name   |      last_update       
----------+------------+--------------+------------------------
        1 | Penelope   | Guiness      | 2013-05-26 14:47:57.62
        2 | Nick       | Wahlberg     | 2013-05-26 14:47:57.62
        3 | Ed         | Chase        | 2013-05-26 14:47:57.62
        4 | Jennifer   | Davis        | 2013-05-26 14:47:57.62
        5 | Johnny     | Lollobrigida | 2013-05-26 14:47:57.62
        6 | Bette      | Nicholson    | 2013-05-26 14:47:57.62
        7 | Grace      | Mostel       | 2013-05-26 14:47:57.62
        8 | Matthew    | Johansson    | 2013-05-26 14:47:57.62
        9 | Joe        | Swank        | 2013-05-26 14:47:57.62
       10 | Christian  | Gable        | 2013-05-26 14:47:57.62
       11 | Zero       | Cage         | 2013-05-26 14:47:57.62
       12 | Karl       | Berry        | 2013-05-26 14:47:57.62
       13 | Uma        | Wood         | 2013-05-26 14:47:57.62
       14 | Vivien     | Bergen       | 2013-05-26 14:47:57.62
       15 | Cuba       | Olivier      | 2013-05-26 14:47:57.62
       16 | Fred       | Costner      | 2013-05-26 14:47:57.62
       17 | Helen      | Voight       | 2013-05-26 14:47:57.62
       18 | Dan        | Torn         | 2013-05-26 14:47:57.62
       19 | Bob        | Fawcett      | 2013-05-26 14:47:57.62
       20 | Lucille    | Tracy        | 2013-05-26 14:47:57.62
(20 rows)

oci_dvdrental=> select count(*) from actor;
 count 
-------
   200
(1 row)

oci_dvdrental=> select * from film_actor limit 10;
 actor_id | film_id |     last_update     
----------+---------+---------------------
        1 |       1 | 2006-02-15 10:05:03
        1 |      23 | 2006-02-15 10:05:03
        1 |      25 | 2006-02-15 10:05:03
        1 |     106 | 2006-02-15 10:05:03
        1 |     140 | 2006-02-15 10:05:03
        1 |     166 | 2006-02-15 10:05:03
        1 |     277 | 2006-02-15 10:05:03
        1 |     361 | 2006-02-15 10:05:03
        1 |     438 | 2006-02-15 10:05:03
        1 |     499 | 2006-02-15 10:05:03
(10 rows)

oci_dvdrental=> select * from store limit 10;
 store_id | manager_staff_id | address_id |     last_update     
----------+------------------+------------+---------------------
        1 |                1 |          1 | 2006-02-15 09:57:12
        2 |                2 |          2 | 2006-02-15 09:57:12
(2 rows)

oci_dvdrental=> select * from city limit 10;
 city_id |        city        | country_id |     last_update     
---------+--------------------+------------+---------------------
       1 | A Corua (La Corua) |         87 | 2006-02-15 09:45:25
       2 | Abha               |         82 | 2006-02-15 09:45:25
       3 | Abu Dhabi          |        101 | 2006-02-15 09:45:25
       4 | Acua               |         60 | 2006-02-15 09:45:25
       5 | Adana              |         97 | 2006-02-15 09:45:25
       6 | Addis Abeba        |         31 | 2006-02-15 09:45:25
       7 | Aden               |        107 | 2006-02-15 09:45:25
       8 | Adoni              |         44 | 2006-02-15 09:45:25
       9 | Ahmadnagar         |         44 | 2006-02-15 09:45:25
      10 | Akishima           |         50 | 2006-02-15 09:45:25
(10 rows)
```

</div></details>

# まとめ
2023/11/15に、OCI Database with PostgreSQLがGAになったため、
一般的な手順でのRDSからの移行を試してみました。

サービスリリース記事

https://blogs.oracle.com/oracle4engineer/post/oci-database-with-postgresql-ga

OCI Database with PostgreSQLの公式ドキュメント（2023/11/15時点では日本語マニュアルナシ）

https://docs.oracle.com/en-us/iaas/Content/postgresql/home.htm

# 参考

https://www.postgresqltutorial.com/postgresql-getting-started/postgresql-sample-database/

https://www.postgresql.org/download/

https://www.postgresql.jp/document/15/html/app-pgdump.html

https://www.postgresql.jp/document/15/html/app-pgrestore.html