[OCI]Oracle Database CloudでCDB内にキャラクタセットの異なるPDBが混在する環境を作ってみた


# はじめに
キャラクタセットが「AL32UTF8」であるCDBに、キャラクタセットが「AL32UTF8」のPDBと「JA16SJIS」のPDBを混在させたいというお話があったので、キャラクタセットが「AL32UTF8」のDBCSインスタンスと「JA16SJIS」のDBCSインスタンスを用意して、PDBの再配置によって実現する手順を検証してみました。

```
＜ソース側DB＞
DBCSインスタンス作成時のキャラクタセット：JA16SJIS
DB名；SJISDB
PDB名：SJISPDB
ホスト：sjisdb.subnet1.vcn1.oraclevcn.com
```

```
＜ターゲット側DB＞
DBCSインスタンス作成時のキャラクタセット：AL32UTF8
DB名；UTF8DB
PDB名：UTF8PDB
ホスト：utf8db.subnet1.vcn1.oraclevcn.com
```

なお、CDBルートに直接プラグインされる場合、CDBのキャラクタセットはPDBのキャラクタセットと同じ、またはスーパーセットである必要があります。
CDBのキャラクタセットがAL32UTF8である場合、PDBのデータベース・キャラクタ・セットに関係なく、プラグイン操作は成功します。 

# 1.ソース（PDBの移動元）側DBでの作業
SYSDBAとしてDBに接続します。

```
[oracle@sjisdb ~]$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Jun 4 20:52:11 2021
Version 19.11.0.0.0

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


Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.11.0.0.0
```
接続先を確認します。

```
SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT
```
CDBのキャラクタセットを確認します。

```
SQL> col parameter for a20
SQL> col value for a30
SQL> SELECT parameter, value FROM v$nls_parameters WHERE parameter='NLS_CHARACTERSET';

PARAMETER	     VALUE
-------------------- ------------------------------
NLS_CHARACTERSET     JA16SJIS
```
JA16SJISであることがわかりました。

PDBの一覧を確認します。

```
SQL> col name for a20
SQL> SELECT dbid, name,open_mode FROM v$pdbs;

      DBID NAME 		OPEN_MODE
---------- -------------------- ----------
3128296700 PDB$SEED		READ ONLY
2198425545 SJISPDB		READ WRITE
```
「SJISPDB」という名前のPDBが存在することが確認できました。

PDB「SJISPDB」に接続します。

```
SQL> ALTER SESSION SET CONTAINER = sjispdb;

Session altered.
```
接続先を確認します。

```
SQL> show con_name

CON_NAME
------------------------------
SJISPDB
```
「SJISPDB」に接続していることが確認できました。

PDB「SJISPDB」のキャラクタセットを確認します。


```
SQL> SELECT parameter, value FROM v$nls_parameters WHERE parameter='NLS_CHARACTERSET';

PARAMETER	     VALUE
-------------------- ------------------------------
NLS_CHARACTERSET     JA16SJIS
```
PDB「SJISPDB」のキャラクタセットが「JA16SJIS」であることが確認できました。

CDBルートに接続します。

```
SQL> ALTER SESSION SET CONTAINER = cdb$root;

Session altered.
```
接続先の確認を確認します。

```
SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT
```
CDBルートに接続していることが確認できました。

PDB再配置用ユーザを作成します。

```
SQL> 
SQL> CREATE USER c##remote_clone_user IDENTIFIED BY Demo#1Demo#1 CONTAINER=ALL;

User created.
```
PDB再配置用ユーザに必要な権限を付与します。

```
SQL> GRANT CREATE SESSION, SYSOPER, CREATE PLUGGABLE DATABASE TO c##remote_clone_user CONTAINER=ALL;

Grant succeeded.
```
以上でソース側DBの作業は完了です。

# 2.ターゲット（PDBの移動先）側DBでの作業
tnsnames.oraにSJSIDBに接続するための接続エイリアスを追加します。

```
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/19.0.0.0/dbhome_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

LISTENER_UTF8DB =
  (ADDRESS = (PROTOCOL = TCP)(HOST = utf8db)(PORT = 1521))


UTF8DB_NRT177 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = utf8db)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = UTF8DB_nrt177.subnet1.vcn1.oraclevcn.com)
    )
  )

## SJISDBへの接続エイリアス
SJISDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = sjisdb.subnet1.vcn1.oraclevcn.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = SJISDB_nrt1sr.subnet1.vcn1.oraclevcn.com)
    )
  )
```
SJISDBへの接続エイリアスが正しく設定できているかを確認します。

```
[oracle@utf8db ~]$ sqlplus system/Demo#1Demo#1@sjisdb

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Jun 4 21:05:01 2021
Version 19.11.0.0.0

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

Last Successful login time: Fri Jun 04 2021 20:28:45 +09:00

Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.11.0.0.0

SQL> exit
```
SYSDBAとしてUTF8DBに接続します。

```
oracle@utf8db ~]$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Jun 4 21:06:44 2021
Version 19.11.0.0.0

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


Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.11.0.0.0

SQL> 
```
接続先を確認します。

```
SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT
```
CDBルートに接続していることが確認できました。

CDBのキャラクタセットを確認します。

```
SQL> col parameter for a20
SQL> col value for a30
SQL> SELECT parameter, value FROM v$nls_parameters WHERE parameter='NLS_CHARACTERSET';

PARAMETER	     VALUE
-------------------- ------------------------------
NLS_CHARACTERSET     AL32UTF8
```
CDBのキャラクタセットが「AL32UTF8」であることが確認できました。

既存のPDBを確認します。

```
SQL> col name for a20
SQL> SELECT dbid,name, open_mode FROM v$pdbs;

      DBID NAME 		OPEN_MODE
---------- -------------------- ----------
1100021415 PDB$SEED		READ ONLY
1195479388 UTF8PDB		READ WRITE
```
CDB「UTF8PDB」が存在することが確認できました。

PDB「UTF8PDB」に接続します。

```
SQL> ALTER SESSION SET CONTAINER = utf8pdb;

Session altered.
```
接続先を確認します。

```
SQL> show con_name

CON_NAME
------------------------------
UTF8PDB
```
PDB「UTF8PDB」に接続していることが確認できました。

PDB「UTF8PDB」のキャラクタセットを確認します。

```
SQL> SELECT parameter, value FROM v$nls_parameters WHERE parameter='NLS_CHARACTERSET';

PARAMETER	     VALUE
-------------------- ------------------------------
NLS_CHARACTERSET     AL32UTF8
```
PDB「UTF8PDB」のキャラクタセットが「AL32UTF8」であることが確認できました。

CDBルートに接続します。

```
SQL> ALTER SESSION SET CONTAINER = cdb$root;

Session altered.
```
接続先を確認します。

```
SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT
```
CDBルートに接続していることが確認できました。

CDB上でSJISDBへのデータベース・リンク「SJISDB」を作成します。

```
SQL> CREATE PUBLIC DATABASE LINK sjisdb CONNECT TO c##remote_clone_user IDENTIFIED BY Demo#1Demo#1 USING 'SJISDB';

Database link created.
```
作成したデータベース・リンクを使用して、CDB「SJISDB」上のPDB「SJISPDB」をCDB「UTF8DB」上に再配置します。
DBCS上のデータベースは暗号化されているので、"keystore identified by"句で暗号化パスワード（DBCSの場合、デフォルトでは管理者パスワードと同じ）を指定します。

```
SQL> CREATE PLUGGABLE DATABASE sjispdb FROM sjispdb@sjisdb RELOCATE AVAILABILITY MAX keystore identified by Demo#1Demo#1;

Pluggable database created.
```
再配置したPDBのオープンモードを確認します。

```
SQL> SELECT dbid,name, open_mode FROM v$pdbs;

      DBID NAME 		OPEN_MODE
---------- ------------ ----------
1100021415 PDB$SEED		READ ONLY
1195479388 UTF8PDB		READ WRITE
2198425545 SJISPDB		MOUNTED
```
再配置したPDB「SJISPDB」はマウント・モードであることがわかります。

PDB「SJISPDB」をオープンします。
再配置されたPDBをオープンすると、ソース側のPDBはクローズされます。

```
SQL> ALTER PLUGGABLE DATABASE sjispdb OPEN;

Pluggable database altered.
```
PDBのオープンモードを再度確認します。

```
SQL> SELECT dbid,name, open_mode FROM v$pdbs;

      DBID NAME 		OPEN_MODE
---------- ------------ ----------
1100021415 PDB$SEED		READ ONLY
1195479388 UTF8PDB		READ WRITE
2198425545 SJISPDB		READ WRITE
```
PDB「SJISPDB」はオープン・モードになったことがわかります。

PDB「SJISPDB」に接続します。

```
SQL> ALTER SESSION SET CONTAINER = sjispdb;

Session altered.
```
SJISPDBのキャラクタセットを確認します。

```
SQL> SELECT parameter, value FROM v$nls_parameters WHERE parameter='NLS_CHARACTERSET';

PARAMETER	       VALUE
----------------   ------------------------------
NLS_CHARACTERSET   JA16SJIS
```
再配置したPDB「SJISPDB」のキャラクタセットは「JA16SJIS」で、ソースPDBのキャラクタセットを維持していることが確認できました。

CDBルートに接続します。

```
SQL> ALTER SESSION SET CONTAINER = cdb$root;

Session altered.
```
接続先を確認します。

```
SQL> show con_name

CON_NAME
------------------------------
CDB$ROOT
```
CDBルートに接続していることが確認できました。

CDBのキャラクタセットを確認します。

```
SQL> SELECT parameter, value FROM v$nls_parameters WHERE parameter='NLS_CHARACTERSET';

PARAMETER	     VALUE
-------------------- ------------------------------
NLS_CHARACTERSET     AL32UTF8
```
CDBのキャラクタセットが「AL32UTF8」であることが確認できました。

キャラクタセットが「AL32UTF8」であるCDB内にキャラクタセットが「JA16SJIS」をPDBを配置することができました。

# 3.ソース側に残ったツームストンPDBの削除
PDBを再配置すると、ソース側のPDBはツームストンPDBとして残ったままとなるため、これを削除します。

```
[oracle@sjisdb ~]$ sqlplus / as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Jun 4 21:48:10 2021
Version 19.11.0.0.0

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


Connected to:
Oracle Database 19c Standard Edition 2 Release 19.0.0.0.0 - Production
Version 19.11.0.0.0
```
PDBのオープンモードを再度確認します。

```
SQL> col name for a20
SQL> SELECT dbid, name,open_mode FROM v$pdbs;

      DBID NAME 		OPEN_MODE
---------- -------------------- ----------
3128296700 PDB$SEED		READ ONLY
2198425545 SJISPDB		MOUNTED
```
PDB「SJISPDB」がオープンできるか試してみます。

```
SQL> ALTER PLUGGABLE DATABASE sjispdb OPEN;
ALTER PLUGGABLE DATABASE sjispdb OPEN
*
ERROR at line 1:
ORA-65086: cannot open/close the pluggable database
```
再配置済みのため、オープンできませんでした。

ツームストンPDB「SJISPDB」をデータファイルごと削除します。

```
SQL> DROP PLUGGABLE DATABASE sjispdb INCLUDING DATAFILES;

Pluggable database dropped.
```
ツームストンPDB「SJISPDB」が削除されたか確認します。

```
SQL> SELECT dbid, name,open_mode FROM v$pdbs;

      DBID NAME 		OPEN_MODE
---------- ------------ ----------
3128296700 PDB$SEED		READ ONLY
```
ツームストンPDB「SJISPDB」が削除されたことが確認できました。

以上で文字コードの異なるCDB間でのPDBの再配置ができることが確認できました。

# 参考情報

[Oracle Database 19c 管理者ガイド：PDBの再配置](https://docs.oracle.com/cd/F19136_01/multi/relocating-a-pdb.html#GUID-75519361-3DA2-4558-A7E5-64BC16FAFC7D)
[Oracle Database 19c Databaseグローバリゼーション・サポート・ガイド：マルチテナント・コンテナ・データベースのデータベース文字セットの選択](https://docs.oracle.com/cd/F19136_01/nlspg/choosing-character-set.html#GUID-09777A99-B7DD-4695-9B2B-278122131000)