How to Move PDBs across CDBs with different Database Block Sizes with Minimal Downtime

Introduction

Plugging a PDB into a CDB with a different database block size is possible, as in Doc ID 2027614.1. You only need to configure the target’s CDB buffer cache to have buffers of the block size of the PDB to be plugged in, which is done by setting the db_nk_cache_size database parameter in the target CDB.

However, unplug/plug requires some downtime, especially for large databases when you need to move the data files across the network. Recently, a question came around whether PDB cloning and especially refreshable clones will also work across CDBs with different database block sizes.

I did some research but couldn’t find anything about this exact use case. I assumed, as plug-in works, so would cloning. But how many times have I assumed something that was proven wrong?

So let’s give it a try.

The Environment

I will use a 19c database running in Oracle Cloud with an 8k database block size as a target CDB.

But wait, where should I get a source CDB with a different database block size? All Oracle Cloud databases default to the recommended 8k block size. Thinking… thinking… thinking… ah, there was something called DBCA. The last time I used it was sometime in 2018 before joining Oracle to work 100% in the Cloud. Indeed I searched Google to see that dbca is located in $ORACLE_HOME/bin/. I configured display forwarding for my Linux machine and ran dbca. I had to search Google again to know that I needed to choose the “Advanced configuration” and “Custom Database” template to be able to specify a non-default database block size. Finally, I have a CDB with a 16k database block size that I can use as a source CDB.

Prepare the Source CDB (db_block_size=16k)

Prepare the C##SYSOPER user In the source CDB:

SQL> grant create session, sysoper to C##SYSOPER identified by SysOperPw__16k container=all;
 
Grant succeeded.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB16K                         READ WRITE NO

SQL> show parameter db_block_size

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_block_size                        integer     16384

Prepare the Target CDB (db_block_size=8k)

Create a database link on the target CDB pointing to the source CDB:

SQL> create database link DBLINK_TO_16K connect to C##SYSOPER identified by SysOperPw__16k using '(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.1.99)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = cdb16k.subnet1.primaryvcn.oraclevcn.com)))';
 
Database link created.

SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 ORCLPDB                        READ WRITE NO

SQL> show parameter db_block_size

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_block_size                        integer     8192

Create a PDB Clone on the Target CDB

It’s time to clone the 16K PDB into the 8K CDB:

SQL> create pluggable database CLONE16K from PDB16K@DBLINK_TO_16K;
create pluggable database CLONE16K from PDB16K@DBLINK_TO_16K
*
ERROR at line 1:
ORA-65176: system tablespace block size (16384) does not match configured block sizes

Ok, let’s set the db_16k_cache_size database parameter then:

SQL> show parameter db_16k_cache_size;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_16k_cache_size                    big integer 0

SQL> alter system set db_16k_cache_size=1G scope=both;

System altered.

SQL> show parameter db_16k_cache_size;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_16k_cache_size                    big integer 1G

Try to clone again:

SQL> create pluggable database CLONE16K from PDB16K@DBLINK_TO_16K;

Pluggable database created.

SQL> alter pluggable database CLONE16K open;

Pluggable database altered.

Nice! Cloning works.

Create a Refreshable Clone on the Target CDB

Now the refreshable clone:

SQL> create pluggable database REF16K from PDB16K@DBLINK_TO_16K refresh mode every 1 minutes;

Pluggable database created.

col pdb_name for a15
col status for a15
col refresh_mode for a15
col refresh_interval for 999
SQL> select pdb_name, status, refresh_mode, refresh_interval from dba_pdbs where pdb_name='REF16K';

PDB_NAME        STATUS          REFRESH_MODE    REFRESH_INTERVAL
--------------- --------------- --------------- ----------------
REF16K          REFRESHING      AUTO                           1

I also created a table and inserted a few rows on the source PDB, waited a minute (literally), opened the refreshable clone in READ ONLY mode, and was able to see that data created on the source are already synchronized. Hence, refreshable PDB cloning works as well.

SQL> show pdbs;

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 ORCLPDB                        READ WRITE NO
         4 CLONE16K                       READ WRITE NO
         5 REF16K                         READ ONLY  NO

Don’t forget to close the refreshable PDB to continue synchronization. For migrations, the only thing you need is to open the refreshable clone in READ WRITE mode when you are ready to use it for production.

PDB_PLUG_IN_VIOLATIONS

What about messages in the PDB_PLUG_IN_VIOLATIONS view? Was the cloning operation really successful?

set lines 300
col pdb_name for a10
col type for a15
col cause for a15
col status for a15
col message for a80
SQL> select p.pdb_name, v.type, v.cause, v.message 
from pdb_plug_in_violations v join cdb_pdbs p on (v.con_id = p.con_id)
where p.pdb_name in ('CLONE16K', 'REF16K') and cause != 'OPTION';

PDB_NAME   TYPE            CAUSE           STATUS          MESSAGE
---------- --------------- --------------- --------------- --------------------------------------------------------------------------------
REF16K     WARNING         Parameter       RESOLVED        CDB parameter db_block_size mismatch: Previous 16384 Current 8192

The PDB clone CLONE16K is not showing any messages. However, the refreshable clone REF16K is showing a warning regarding the parameter mismatch. Strange! But the status is RESOLVE. The PDB is not in restricted mode, and data are being synchronized.

Block Sizes of the Cloned Data Files

The database files of the source PDB are copied with the same original block size, which is 16K:

set lines 300
col pdb_name for a10
col tablespace_name for a15
col block_size for 99999
SQL> select p.pdb_name, t.tablespace_name, t.block_size 
from cdb_tablespaces t join cdb_pdbs p on (t.con_id = p.con_id)
where p.pdb_name in ('CLONE16K', 'REF16K');

PDB_NAME   TABLESPACE_NAME BLOCK_SIZE
---------- --------------- ----------
REF16K     SYSTEM               16384
REF16K     SYSAUX               16384
REF16K     UNDOTBS1             16384
REF16K     TEMP                 16384
REF16K     USERS                16384
CLONE16K   SYSTEM               16384
CLONE16K   SYSAUX               16384
CLONE16K   UNDOTBS1             16384
CLONE16K   TEMP                 16384
CLONE16K   USERS                16384

This is why you need to set the db_16k_cache_size database parameter on the target CDB.

Conclusion

Oracle Multitenant allows you to move PDBs around even across CDBs with different database block sizes, using the unplug/plug, cloning, or refreshable clones to minimize downtime. For this to work, you need to set the db_nk_cache_size database parameter in the target CDB beforehand accordingly.

Further Reading

Would you like to get notified when the next post is published?