DBMS_FILE_TRANSFERパッケージでDB(11gR2) -> DBLINK -> PDB(12cR2)のデータファイルの転送(コピー)を実行する。(Oracle Database)

DBMS_FILE_TRANSFERパッケージで中間ファイルを介さずに、
DB(11gR2) to PDB(12cR2) の直接のファイル転送(コピー)を
実行してみますやで彡(ﾟ)(ﾟ)

 > Oracle Database PL/SQL Packages and Types Reference 12c Release 2 (12.2)
 > 67 DBMS_FILE_TRANSFER
 > https://docs.oracle.com/en/database/oracle/oracle-database/12.2/arpls/DBMS_FILE_TRANSFER.html#GUID-9E206058-78CB-4028-8883-7C28B845F86C

今回試すのは以下のような接続トポロジです。

```
11gR2(データファイルのコピー元) ⇒ DBLINK ⇒ 12cR2(コピー先、DBMS_FILE_TRANSFERを実行)
```
# 1. データファイルのコピー元にディレクトリ・オブジェクトを作成

データファイルのパスを参照可能なディレクトリ・オブジェクトを作成して、
READ権限を付与します。下記例では専用ユーザーを作成していますが、必須ではありません。

```sql
-- 11gR2(ユーザー作成)
CREATE USER FILETRANS IDENTIFIED BY xxxxxxxx
DEFAULT TABLESPACE USERS
TEMPORARY TABLESPACE TEMP;
GRANT CREATE SESSION TO FILETRANS;

-- 11gR2(ディレクトリ・オブジェクト作成)
CREATE DIRECTORY DIR_DATAFILE as '+DATA/ORCL/DATAFILE';
GRANT READ ON DIRECTORY DIR_DATAFILE TO FILETRANS;

User created.

Grant succeeded.

Directory created.

Grant succeeded.
```

# 2. データファイルのコピー先(PDB)にディレクトリ・オブジェクトを作成

データファイルのコピー先(PDB)のパスにアクセス可能なディレクトリ・オブジェクトを
PDB上に作成して、DBMS_FILE_TRANSFERパッケージを実行するユーザーに
ディレクトリ・オブジェクトのWRITE権限を付与します。

```sql
-- 12cR2
CONNECT /AS SYSDBA
ALTER SESSION SET CONTAINER = PDB01;
SHOW CON_NAME;
CREATE DIRECTORY DIR_DATAFILE_PDB01 as '/u01/app/oracle/oradata/AYUCDB/6C4B2D3386C20FB8E055000000000001/datafile/';
GRANT WRITE ON DIRECTORY DIR_DATAFILE_PDB01 TO AYSHIBAT;

Connected.

Session altered.

CON_NAME
------------------------------
PDB01

Directory created.

Grant succeeded.
```

# 3. データファイルのコピー先(PDB)に、コピー元へ接続するDBLINKを作成

データファイルのコピー先(PDB)に、コピー元(今回は11gR2)へ接続する
DBLINK(DATABASE LINK)を作成します。コピー元の接続ユーザーは、
コピーするデータファイルのディレクトリ・オブジェクトのREAD権限が必要です。

```sql
-- 12cR2
CONNECT AYSHIBAT/xxxxxxxx@PDB01
SHOW CON_NAME;
CREATE DATABASE LINK DBL_ORCL_11GR2
CONNECT TO FILETRANS IDENTIFIED BY xxxxxxxx
USING 'ORCL_11GR2';

-- DBLINKの動作確認
SET LINESIZE 170;
SELECT * FROM V$VERSION@DBL_ORCL_11GR2;
SELECT * FROM V$VERSION;

Connected.

CON_NAME
------------------------------
PDB01

Database link created.

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE    11.2.0.4.0      Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

BANNER                                                                               CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production              0
PL/SQL Release 12.2.0.1.0 - Production                                                    0
CORE    12.2.0.1.0      Production                                                        0
TNS for Linux: Version 12.2.0.1.0 - Production                                            0
NLSRTL Version 12.2.0.1.0 - Production                                                    0
```

# 4. DBMS_FILE_TRANSFERパッケージのGET_FILEプロシージャを実行して、データファイルをコピー
コピー先(今回は12cR2側)でDBMS_FILE_TRANSFERパッケージの
GET_FILEプロシージャを実行して、データファイルをコピーします。


```sql
-- 12cR2
BEGIN
  DBMS_FILE_TRANSFER.GET_FILE(
      'DIR_DATAFILE'            -- 11gR2側のディレクトリ・オブジェクト
    , 'tbs_tts1.266.979841605'  -- 11gR2側のデータファイル名
    , 'DBL_ORCL_11GR2'          -- 12cR2 ⇒ 11gR2 の DBLINK名
    , 'DIR_DATAFILE_PDB01'      -- 12cR2側のディレクトリ・オブジェクト
    , 'tbs_tts1.266.979841605'  -- 12cR2側のデータファイル名
  );
END;
/

BEGIN
  DBMS_FILE_TRANSFER.GET_FILE(
      'DIR_DATAFILE'            -- 11gR2側のディレクトリ・オブジェクト
    , 'tbs_tts2.267.979841605'  -- 11gR2側のデータファイル名
    , 'DBL_ORCL_11GR2'          -- 12cR2 ⇒ 11gR2 の DBLINK名
    , 'DIR_DATAFILE_PDB01'      -- 12cR2側のディレクトリ・オブジェクト
    , 'tbs_tts2.267.979841605'  -- 12cR2側のデータファイル名
  );
END;
/
```

```shell
# DBMS_FILE_TRANSFER実行前
$ pwd
/u01/app/oracle/oradata/AYUCDB/6C4B2D3386C20FB8E055000000000001/datafile
$ ls -la
total 1133172
drwxr-x---. 2 oracle oinstall      4096 Jun 27 14:26 .
drwxr-x---. 3 oracle oinstall      4096 May 16 12:19 ..
-rw-r-----. 1 oracle oinstall 398467072 Jun 27 14:25 o1_mf_sysaux_fhq8s86l_.dbf
-rw-r-----. 1 oracle oinstall 272637952 Jun 27 14:37 o1_mf_system_fhq8s865_.dbf
-rw-r-----. 1 oracle oinstall 135274496 Jun 26 19:11 o1_mf_temp_fhq8s86n_.dbf
-rw-r-----. 1 oracle oinstall 104865792 Jun 27 14:37 o1_mf_undotbs1_fhq8s86m_.dbf
-rw-r-----. 1 oracle oinstall 259530752 Jun 27 13:47 o1_mf_users_fhq8s86o_.dbf
```

```sql
SQL> BEGIN
  2    DBMS_FILE_TRANSFER.GET_FILE(
  3        'DIR_DATAFILE'            -- 11gR2側のディレクトリ・オブジェクト
  4      , 'tbs_tts1.266.979841605'  -- 11gR2側のデータファイル名
  5      , 'DBL_ORCL_11GR2'          -- 12cR2 ⇒ 11gR2 の DBLINK名
  6      , 'DIR_DATAFILE_PDB01'      -- 12cR2側のディレクトリ・オブジェクト
  7      , 'tbs_tts1.266.979841605'  -- 12cR2側のデータファイル名
  8    );
  9  END;
 10  /

PL/SQL procedure successfully completed.

SQL> BEGIN
  2    DBMS_FILE_TRANSFER.GET_FILE(
  3        'DIR_DATAFILE'            -- 11gR2側のディレクトリ・オブジェクト
  4      , 'tbs_tts2.267.979841605'  -- 11gR2側のデータファイル名
  5      , 'DBL_ORCL_11GR2'          -- 12cR2 ⇒ 11gR2 の DBLINK名
  6      , 'DIR_DATAFILE_PDB01'      -- 12cR2側のディレクトリ・オブジェクト
  7      , 'tbs_tts2.267.979841605'  -- 12cR2側のデータファイル名
  8    );
  9  END;
 10  /

PL/SQL procedure successfully completed.
```

```shell
# DBMS_FILE_TRANSFER実行後
$ pwd
/u01/app/oracle/oradata/AYUCDB/6C4B2D3386C20FB8E055000000000001/datafile
$ ls -la
total 1153668
drwxr-x---. 2 oracle oinstall      4096 Jun 27 14:40 .
drwxr-x---. 3 oracle oinstall      4096 May 16 12:19 ..
-rw-r-----. 1 oracle oinstall 398467072 Jun 27 14:25 o1_mf_sysaux_fhq8s86l_.dbf
-rw-r-----. 1 oracle oinstall 272637952 Jun 27 14:37 o1_mf_system_fhq8s865_.dbf
-rw-r-----. 1 oracle oinstall 135274496 Jun 26 19:11 o1_mf_temp_fhq8s86n_.dbf
-rw-r-----. 1 oracle oinstall 104865792 Jun 27 14:37 o1_mf_undotbs1_fhq8s86m_.dbf
-rw-r-----. 1 oracle oinstall 259530752 Jun 27 13:47 o1_mf_users_fhq8s86o_.dbf
-rw-r-----. 1 oracle oinstall  10493952 Jun 27 14:40 tbs_tts1.266.979841605 ★コピーされたデータファイル
-rw-r-----. 1 oracle oinstall  10493952 Jun 27 14:40 tbs_tts2.267.979841605 ★コピーされたデータファイル
$
```

見事にデータファイルがコピーされましたやで！彡(^)(^)

# 5. まとめ

cpやscp等によるファイルシステム(中間ファイル)を介した転送と異なって、
DBMS_FILE_TRANSFERパッケージは DB to DB による直接のファイル転送(コピー)が
実現できるんやで彡(^)(^) ＃中間ファイルを介さないので理論上は速い。

転送中(転送経路上)の圧縮ができるとより理想的なんやけど、
下記パラメータ(SQLNET.COMPRESSION)を使ったら実現可能なんやろうか……？ 彡(ﾟ)(ﾟ)

 > Oracle Database Net Servicesリファレンス 12cリリース2 (12.2)
 > 5.2.20 SQLNET.COMPRESSION
 > https://docs.oracle.com/cd/E82638_01/netrf/parameters-for-the-sqlnet-ora-file.html#GUID-61CE4FA9-3ABB-4E9B-B788-FB57E6B56F47
 > データ圧縮を有効または無効にします。サーバー、クライアントの両方ともこのパラメータをONに設定している場合、接続に圧縮が使用されます。