
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.