Multitenant: Einhängen einer Non-CDB mit anderer Blockgröße

23. April 2024 Aus Von Markus Flechtner

Die am häufigsten genutzte Blockgröße bei Oracle sind 8 KB. Andere Standard-Blockgrößen sind selten. Und eine Mischung aus verschiedenen Blockgrößen ebenfalls. Aber was passiert, wenn man im Rahmen einer Konsolidierung, Datenbanken mit unterschiedlichen Standard-Blockgrößen in einer Container-Datenbank zusammenführen will.

Wir starten unseren Test mit zwei Datenbanken:

  1. eine CDB mit Namen CDB8K und einer Default-Blockgröße von 8KB
  2. eine NonCDB mit Namen NCDB32K mit einer Default-Blockgröße von 32KB

Beide Datenbanken haben den Patch-Stand Oracle 19c – 19.22:

oracle@kiwi:~/ $ORACLE_HOME/OPatch/opatch lspatches
36092868;DATAPUMP BUNDLE PATCH 19.22.0.0.0
35949090;JDK BUNDLE PATCH 19.0.0.0.240116
35926646;OJVM RELEASE UPDATE: 19.22.0.0.240116 (35926646)
35943157;Database Release Update : 19.22.0.0.240116 (35943157)
29585399;OCW RELEASE UPDATE 19.3.0.0.0 (29585399)

OPatch succeeded.

Und wir wollen jetzt die Datenbank NCDB232K als PDB in die CDB8K einhängen.

Vorbereitungen

Öffnen der Non-CDB im Read-Only-Modus

SQL> startup open read only;
ORACLE instance started.

Total System Global Area 8589930736 bytes
Fixed Size 13693168 bytes
Variable Size 1459617792 bytes
Database Buffers 7096762368 bytes
Redo Buffers 19857408 bytes
Database mounted.
Database opened.

Manifest-Datei erzeugen

SQL> execute dbms_pdb.describe(pdb_descr_file=>'/home/oracle/ncdb32k.xml');
PL/SQL procedure successfully completed.

SQL> !ls -ltr /home/oracle/ncdb32k.xml
-rw-r--r--. 1 oracle oinstall 7674 Apr 24 08:44 /home/oracle/ncdb32k.xml

SQL> !grep block_size /home/oracle/ncdb32k.xml
<parameter>db_block_size=32768</parameter>

Non-CDB schließen

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.

Kompatibilitätsprüfung

Mit folgendem Code aus der MOS-Note 2012448.1 können wir prüfen, ob die Non-CDB mit der CDB kompatibel ist (wir wissen natürlich, dass sie das aufgrund der unterschiedlichen Blockgrößen nicht ist)

SET SERVEROUTPUT ON;
DECLARE
compatible CONSTANT VARCHAR2(3) := CASE DBMS_PDB.CHECK_PLUG_COMPATIBILITY(pdb_descr_file => '/home/oracle/ncdb32k.xml')
WHEN TRUE THEN 'YES'
ELSE 'NO'
END;
BEGIN
DBMS_OUTPUT.PUT_LINE(compatible);
END;
/

Ergebnis:

SET SERVEROUTPUT ON;
SQL> DECLARE
compatible CONSTANT VARCHAR2(3) := CASE DBMS_PDB.CHECK_PLUG_COMPATIBILITY(pdb_descr_file => '/home/oracle/ncdb32k.xml')
3 WHEN TRUE THEN 'YES'
4 ELSE 'NO'
5 END;
6 BEGIN
7 DBMS_OUTPUT.PUT_LINE(compatible);
8 END;
9 /
NO

PL/SQL procedure successfully completed.

Wie erwartet, ist die Non-CDB also nicht zur CDB kompatibel.

Ein Blick in die PDB_PLUG_IN_VIOLATIONS zeigt, dass der Kompatibilitätscheck das Problem mit den Blockgrößen erkannt hat.

SQL> SELECT name, cause, status, action, message 
2 FROM pdb_plug_in_violations WHERE status<>'RESOLVED';


NAME CAUSE STATUS ACTION
---------- ---------------------------------------- --------- ------------
MESSAGE
--------------------------------------------------------------------------
[...]
NCDB32K Parameter PENDING Please check the parameter in the current CDB
CDB parameter db_block_size mismatch: Previous 32768 Current 8192
[...]

Non-CDB einhängen – 1.Versuch

Was passiert, wenn wir trotzdem versuchen, die Non-CDB einzuhängen?

SQL> create pluggable database ncdb32k using '/home/oracle/ncdb32k.xml' nocopy;
create pluggable database ncdb32k using '/home/oracle/ncdb32k.xml' nocopy
*
ERROR at line 1:
ORA-65176: system tablespace block size (32768) does not match configured block sizes

Cache für 32K-Blöcke einrichten

Also richten wir mal einen Cache für 32K-Blöcke ein:

SQL> show parameter db_32k_cache_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_32k_cache_size big integer 0

SQL> alter system set db_32k_cache_size=1G scope=spfile;
System altered.

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 3154114056 bytes
Fixed Size 9184776 bytes
Variable Size 553648128 bytes
Database Buffers 2583691264 bytes
Redo Buffers 7589888 bytes
Database mounted.
Database opened.

SQL> show parameter db_32k_cache_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_32k_cache_size big integer 1G

Non-CDB einhängen: 2.Versuch

SQL> create pluggable database ncdb32k using '/home/oracle/ncdb32k.xml' nocopy;
create pluggable database ncdb32k using '/home/oracle/ncdb32k.xml' nocopy
*
ERROR at line 1:
ORA-27038: created file already exists
ORA-01119: error in creating database file '/u01/oradata/NCDB32K/temp01.dbf'

Temp-Files werden beim Einhängen einer Datenbank neu angelegt, daher benennen wir die Datei einfach um:

SQL> !mv /u01/oradata/NCDB32K/temp01.dbf /u01/oradata/NCDB32K/temp01.dbf-old
SQL> create pluggable database ncdb32k using '/home/oracle/ncdb32k.xml' nocopy;
Pluggable database created.

Mit dem konfigurierten 32K-Cache können wir die Non-CDB also problemlos einhängen.

Dictionary-Konvertierung

SQL> alter session set container=NCDB32K;
Session altered.

SQL> @?/rdbms/admin/noncdb_to_pdb.sql
[...]
SQL> -- leave the PDB in the same state it was when we started
SQL> BEGIN
2 execute immediate '&open_sql &restricted_state';
3 EXCEPTION
4 WHEN OTHERS THEN
5 BEGIN
6 IF (sqlcode <> -900) THEN
7 RAISE;
8 END IF;
9 END;
10 END;
11 /

PL/SQL procedure successfully completed.

SQL>
SQL> WHENEVER SQLERROR CONTINUE;
SQL>

PDB öffnen

SQL> alter pluggable database ncdb32k open;
Pluggable database altered.

Was ist jetzt in so einer Konfiguration zu beachten?

SQL> alter session set container=NCDB32K;
Session altered.

Die Blockgröße der eingehängten Tablespaces bleibt bei 32K:

SQL> select tablespace_name,block_size from dba_tablespaces;

TABLESPACE_NAME BLOCK_SIZE
------------------------------ ----------
SYSTEM 32768
SYSAUX 32768
UNDOTBS1 32768
TEMP 32768
USERS 32768
EXAMPLE 32768

6 rows selected.

Das war zu erwarten, denn beim Einhängen werden die Dateien nicht konvertiert.

Der Parameter DB_BLOCK_SIZE zeigt 8K, nämlich die Standard-Blockgröße der CDB:

SQL> show parameter db_block_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_size integer 8192

und eine Änderung ist – wenig überraschend – auf PDB-Ebene nicht möglich:

SQL> alter system set db_block_size=32768 scope=spfile;
alter system set db_block_size=32768 scope=spfile
*
ERROR at line 1:
ORA-65040: operation not allowed from within a pluggable database

Was passiert, wenn wir einen neuen Tablespace anlegen?

Ein neuer Tablespace in der PDB wird mit einer Blockgröße von 32K angelegt (die Blockgröße des SYSTEM-Tablespaces wird als Default genutzt) – und mdas ist zugegebenermassen ein Punkt, der mich überrascht hat:

SQL> create tablespace TEST 
2 datafile '/u01/oradata/NCDB32K/test01.dbf' size 100M;
Tablespace created.

SQL> select tablespace_name,block_size from dba_tablespaces
2 where tablespace_name like 'TEST%';
TABLESPACE_NAME BLOCK_SIZE
------------------------------ ----------
TEST 32768
1 row selected.

Wenn man einen Tablespace mit 8KB-Blockgröße, also der Standard-Blockgröße der CDB, anlegen will, muss man das explizit angeben:

SQL> create tablespace TEST8K 
2 datafile '/u01/oradata/NCDB32K/test8k01.dbf' size 100M blocksize 8K;
Tablespace created.

SQL> select tablespace_name,block_size from dba_tablespaces
2 where tablespace_name like 'TEST%';
TABLESPACE_NAME BLOCK_SIZE
------------------------------ ----------
TEST 32768
TEST8K 8192

2 rows selected.

Links & MOS-Notes:

  • Different block sizes when you plugin? – mikedietrichde.com
  • MOS-Note: ORA-65154: “system tablespace block size (16384) does not match root’s block size” When Plugging in a PDB (Doc ID 1985930.1)
  • MOS-Note: Can I Plug in a PDB to a CDB If Their Values of the DB_BLOCK_SIZE Parameter are Different (Doc ID 2027614.1)