Eine Oracle 19 non-CDB auf File System wird mittels Physical Standby und Data Guard auf eine andere Maschine migriert. Auf der Ziel-Maschine wird die Datenbank in eine Pluggable Database (PDB) konvertiert. Die alte non-CDB wird dabei als Fallback-Lösung erhalten. Auf der Zielmaschine läuft bereits eine CDB$ROOT die ASM nutzt. Dieses Vorgehen kann so für eine Testmigration als auch für die eigentliche Migration angewendet werden.
Vorhandene Struktur und Ausgangssituation
Quelle Ziel
--------------------------------------------------
Host: oracle-srv4 oracle-srv6
DB_NAME: TISLI ILTIS
PATCH: 19.21.0.0.231017 19.21.0.0.231017
CDB nonCDB CDB
PDB nein ja, Name: ILTIS
ASM nein ja, Diskgroup: DATA01
TEIL 1: Physical Standby erzeugen
In diesem Schritt wird auf der Ziel-Maschine eine Physical Standby Datenbank erzeugt, welche direkt ASM nutzt.
Primary Database vorbereiten
Force Logging und dg_broker Parameter einstellen
alter database force logging;
select name, force_logging from v$database;
alter system set dg_broker_start=true scope=both;
Standby Logfiles auf Primary erzeugen
Anzahl Standby Logfile [n] = Thread * Redologfiles[n] + 1
Die Größe der Standby Logfiles sollte hierbei der Größe der Redologfiles entsprechen.
alter database add standby logfile group 11 ('/u01/app/oracle/oradata/TISLI/standby11.log') size 200M;
alter database add standby logfile group 12 ('/u01/app/oracle/oradata/TISLI/standby12.log') size 200M;
alter database add standby logfile group 13 ('/u01/app/oracle/oradata/TISLI/standby13.log') size 200M;
alter database add standby logfile group 14 ('/u01/app/oracle/oradata/TISLI/standby14.log') size 200M;
Oracle Net Konfiguration
tnsnames.ora der oracle-srv4
LISTENER_TISLI =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-srv4.example.cnh)(PORT = 1522))
TISLI =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-srv4.example.cnh)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = TISLI.example.cnh)
)
)
ILTIS =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-srv6.example.cnh)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ILTIS.example.cnh)
(UR = A)
)
)
tnsnames.ora der oracle-srv6
ILTIS_LISTENER =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-srv6.example.cnh)(PORT = 1522))
ILTIS =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-srv6.example.cnh)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ILTIS.example.cnh)
(UR = A)
)
)
TISLI =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-srv4.example.cnh)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = TISLI.example.cnh)
)
)
listener.ora der oracle-srv4
TISLI_LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-srv4.example.cnh)(PORT = 1522))
)
)
SID_LIST_LISTENER_TISLI =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = TISLI_DGMGRL.example.cnh)
(SERVICE_NAME = TISLI.example.cnh)
(SID_NAME = TISLI)
(ORACLE_HOME=/u01/app/oracle/product/19.0.0/db19300)
)
)
listener.ora der oracle-srv6
ILTIS_LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = oracle-srv6.example.cnh)(PORT = 1522))
)
)
SID_LIST_ILTIS_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = ILTIS_DGMGRL.example.cnh)
(SERVICE_NAME = ILTIS.example.cnh)
(SID_NAME = ILTIS)
(ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1)
)
)
Listener auf Ziel-Maschine starten
lsnrctl start ILTIS_LISTENER
PFILE von der Quell-DB erzeugen
create pfile='/home/oracle/initTISLI.ora' from spfile;
Das PFILE:
TISLI.__data_transfer_cache_size=0 TISLI.__db_cache_size=788529152 TISLI.__inmemory_ext_roarea=0 TISLI.__inmemory_ext_rwarea=0 TISLI.__java_pool_size=0 TISLI.__large_pool_size=16777216 TISLI.__oracle_base='/u01/app/oracle'#ORACLE_BASE set from environment TISLI.__pga_aggregate_target=402653184 TISLI.__sga_target=1191182336 TISLI.__shared_io_pool_size=67108864 TISLI.__shared_pool_size=301989888 TISLI.__streams_pool_size=0 TISLI.__unified_pga_pool_size=0 *.aq_tm_processes=0 *.audit_file_dest='/u01/app/oracle/admin/TISLI/adump' *.audit_trail='db' *.compatible='19.0.0' *.control_files='/u01/app/oracle/oradata/TISLI/control01.ctl','/u01/app/oracle/fast_recovery_area/TISLI/control02.ctl' *.db_block_size=8192 *.db_create_file_dest='/u01/app/oracle/oradata/' *.db_domain='example.cnh' *.db_name='TISLI' *.db_recovery_file_dest='/u01/app/oracle/fast_recovery_area' *.db_recovery_file_dest_size=1000m *.diagnostic_dest='/u01/app/oracle' *.dispatchers='(PROTOCOL=TCP) (SERVICE=TISLIXDB)' *.fal_server='' *.job_queue_processes=0 *.local_listener='LISTENER_TISLI' *.log_archive_dest_state_2='RESET' *.log_archive_format='%t_%s_%r.dbf' *.nls_language='AMERICAN' *.nls_territory='AMERICA' *.open_cursors=300 *.pga_aggregate_target=379m *.processes=300 *.remote_login_passwordfile='EXCLUSIVE' *.sga_target=1136m *.undo_tablespace='UNDOTBS1'
PFILE auf Ziel-Maschine kopieren und anpassen
Das pfile kopieren, in initILTIS.ora
umbenennen und anpassen. Wichtig ist hierbei, dass db_name='TISLI'
ist, da sonst das RMAN duplicate from active database
abbricht.
*.audit_file_dest='/u01/app/oracle/admin/ILTIS/adump'
*.audit_trail='db'
*.compatible='19.0.0'
*.control_files='+DATA01/ILTIS/CONTROLFILE/current.262.1174986935','+DATA01/ILTIS/CONTROLFILE/current.262.1174986935'
*.log_file_name_convert='/u01/app/oracle/oradata/TISLI/','+DATA01/ILTIS/ONLINELOG/'
*.db_file_name_convert='/u01/app/oracle/oradata/TISLI/','+DATA01/ILTIS/DATAFILE/'
*.standby_file_management='AUTO'
*.db_create_file_dest='+DATA01'
*.db_block_size=8192
*.db_domain='example.cnh'
*.db_name='TISLI'
*.db_unique_name=ILTIS
*.db_recovery_file_dest='+DATA01'
*.db_recovery_file_dest_size=1000m
*.diagnostic_dest='/u01/app/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=ILTISXDB)'
*.local_listener='ILTIS_LISTENER'
*.log_archive_format='%t_%s_%r.dbf'
*.nls_language='AMERICAN'
*.nls_territory='AMERICA'
*.open_cursors=300
*.pga_aggregate_target=379m
*.processes=300
*.remote_login_passwordfile='EXCLUSIVE'
*.sga_target=1136m
*.undo_tablespace='UNDOTBS1'
Parameter standby_file_management='AUTO'
setzen, da sonst neu erzeugte Datenfiles der Primary leider dann auf der Standby im File System angelegt werdern. Und das obwohl auf der Standby der Parameter db_create_file_dest=+DATA01
für die Diskgruppe im ASM eingestellt ist.
Password File auf Ziel-Maschine für Standby DB erstellen
orapwd file=/u01/app/oracle/product/19.0.0/dbhome_1/orapwILTIS password=oracle entries=10 format=12
Eintrag in der /etc/oratab auf Ziel-Maschine erstellen
ILTIS:/u01/app/oracle/product/19.0.0/dbhome_1:N
Notwendige Directories auf Ziel-Maschine anlegen
mkdir -p /u01/app/oracle/admin/ILTIS/adump
Standby Instanz auf Ziel-Maschine hochfahren, SPFILE erzeugen und durchstarten
Das spfile Ist notwendig, da sonst das RMAN Duplicate abbricht.
. oraenv --> ILTIS
sqlplus "/ as sysdba"
startup nomount pfile='/u01/app/oracle/product/19.0.0/dbhome_1/initILTIS.ora';
create spfile from pfile='/u01/app/oracle/product/19.0.0/dbhome_1/dbs/initILTIS.ora';
shutdown immediate;
startup nomount;
ORACLE Net Konfiguration prüfen
Jede der beiden Instanzen muss von jeder der beiden Maschinen oracle-srv4 und oracle-srv6 erreichbar sein.
# oracle-srv4: sqlplus sys/oracle@TISLI as sysdba select instance_name, host_name from v$instance; sqlplus sys/oracle@ILTIS as sysdba select instance_name, host_name from v$instance; # oracle-srv6: sqlplus sys/oracle@TISLI as sysdba select instance_name, host_name from v$instance; sqlplus sys/oracle@ILTIS as sysdba select instance_name, host_name from v$instance;
RMAN duplicate database for standby from active database durchführen
In RMAN wird die Quell-DB als „target“ bezeichnet und die Ziel-DB als auxiliary! RMAN wird hier auf der Standby Seite aufgerufen.
rman target sys/oracle@TISLI auxiliary sys/oracle@ILTIS
run
{
allocate channel t1 device type disk;
allocate channel t2 device type disk;
allocate auxiliary channel t3 device type disk;
allocate auxiliary channel t4 device type disk;
duplicate target database for standby from active database dorecover nofilenamecheck;
}
Standby Logfiles auf der Standby erzeugen
Sollten diese noch fehlen, weil vor dem RMAN Duplicate keine auf der Primary angelegt wurden, kann das auf der Standby sowie auf der Primary noch nachgeholt werden.
alter database add standby logfile group 11 '+DATA01' size 200M;
alter database add standby logfile group 12 '+DATA01' size 200M;
alter database add standby logfile group 13 '+DATA01' size 200M;
alter database add standby logfile group 14 '+DATA01' size 200M;
TEMP Tablespace auf Standby prüfen
set lin 180 set pages 4000 col FILENAME format a50 -- SELECT TMP.NAME FILENAME, BYTES/1024/1024 as "MB", TS.NAME TABLESPACE FROM V$TEMPFILE TMP, V$TABLESPACE TS WHERE TMP.TS#=TS.TS#;
Es ist unerheblich, wenn z.B. die Größe 0 ist. Das wird später beim aktivieren der Standby verschwinden. Wichtig ist, dass ein TEMP File da ist.
Data Guard Broker Parameter auf Standby setzen
Der Parameter ist notwendig, sonst lässt sich die Standby nicht in der Data Guard Broker Konfiguration hinzufügen. Auf der Primary wurde dieser ja schon zu Beginn gesetzt.
alter system set dg_broker_start=true scope=both;
Data Guard Broker Konfiguration erzeugen
dgmgrl sys/oracle@TISLI #Hier geht auch dgmgrl sys/oracle@ILTIS
CREATE CONFIGURATION FOR_MIGRATION AS PRIMARY DATABASE IS TISLI CONNECT IDENTIFIER IS TISLI;
ADD DATABASE ILTIS AS CONNECT IDENTIFIER IS ILTIS MAINTAINED AS PHYSICAL;
ENABLE CONFIGURATION;
SHOW CONFIGURATION;
Auf der PRIM einige Logswitches machen.
alter system archive log current;
alter system archive log current;
alter system archive log current;
Data Guard Broker Konfiguration prüfen. Kann 1-2 Minuten dauern bis der Status SUCCESS angezeigt wird.
SHOW CONFIGURATION;
Bei großen Datenbanken kann die so erstellte Physical Standby Datenbank nun bis zum beabsichtigten (Test-)Migrations-Termin weiterlaufen.
TEIL 2: Migration non-CDB to PDB
Bei einer Testmigration wird die alte Primary unterbrechungsfrei weiter produktiv verwendet und die neu erzeugte Primary nur für bestimmte Tests bereitgestellt. Bei der eigentlichen Migration wird die alte Primary rechtzeitig gesperrt und am Ende natürlich nicht mehr verfügbar gemacht.
User auf der Primary sperren und Process Parameter setzen
***Hinweis: Das ist bei einer Testmigration nicht notwendig und die betreffende Datenbank kann weiter ohne Unterbrechung und Einschränkungen genutzt werden.
alter user YOUR_DB_USER account lock;
alter system set job_queue_processes=0 scope=both;
alter system set aq_tm_processes=0 scope=both;
Data Guard Redo Transport und Apply stoppen
Auf der PRIM einige Logswitches machen.
alter system archive log current;
alter system archive log current;
alter system archive log current;
Redo Transport und Apply stoppen.
dgmgrl sys/oracle@TISLI
EDIT DATABASE 'TISLI' SET STATE=TRANSPORT-OFF;
EDIT DATABASE 'iltis' SET STATE='APPLY-OFF';
Data Gurard Broker configuration entfernen
dgmgrl sys/oracle@TISLI
disable CONFIGURATION;
remove CONFIGURATION;
Standby aktivieren
Die Standby wird aktiviert und somit zu einer Primary umgewandelt. Dies wird natürlich auf der Standby-Seite gemacht.
sqlplus / as sysdba
select open_mode, database_role from v$database;
ALTER DATABASE ACTIVATE PHYSICAL STANDBY DATABASE;
select open_mode, database_role from v$database;
SHUTDOWN IMMEDIATE;
STARTUP;
*** Hinweis: Die folgenden Schritte sind auf der alten Primary nur notwendig, wenn diese weiter genutzt werden soll. Wie z.B. bei einer Testmigration oder eben im Falle eines Fallback-Szenario. Zur besseren Übersicht sind diese Schritte in () dargestellt.
(Alte Primary wieder zur Verfügung stellen)
(Auf alter Primary Parameter zurücksetzen)
alter system set dg_broker_start=false scope=both;
alter system reset FAL_SERVER;
alter system reset log_archive_config;
-- Also check if remote archive destination is set, LOG_ARCHIVE_DEST_n
alter system reset log_archive_dest_2 scope=both;
alter system reset log_archive_config scope=both;
(Auf alter Primary die Standby Logfiles droppen)
ALTER DATABASE DROP STANDBY LOGFILE GROUP 11;
ALTER DATABASE DROP STANDBY LOGFILE GROUP 12;
ALTER DATABASE DROP STANDBY LOGFILE GROUP 13;
ALTER DATABASE DROP STANDBY LOGFILE GROUP 14;
(User auf alter Primary wieder entsperren und Process Parameter zurücksetzen)
alter user YOUR_DB_USER account lock;
alter system set job_queue_processes=30 scope=both;
alter system set aq_tm_processes=1 scope=both;
Damit ist die alte Primary (wieder) Verfügbar.
Auf der neuen Primary Data Guard Parameter zurücksetzen
alter system set dg_broker_start=false scope=both;
alter system reset FAL_SERVER;
alter system reset log_archive_config;
alter system reset log_archive_config scope=both;
Auf der neuen Primary die Standby Logfiles droppen
ALTER DATABASE DROP STANDBY LOGFILE GROUP 11;
ALTER DATABASE DROP STANDBY LOGFILE GROUP 12;
ALTER DATABASE DROP STANDBY LOGFILE GROUP 13;
ALTER DATABASE DROP STANDBY LOGFILE GROUP 14;
Konvertieren der neuen Primary von non-CDB nach PDB
Folgende Schritte sind notwendig, um die neue Primary von einer non-CDB zu einer PDB Datenbank zu konvertieren.
Shutdown non-CDB und read only öffnen
select name, cdb, open_mode from v$database;
shutdown immediate;
startup mount;
alter database open read only;
DBMS_PDB.DESCRIBE ausführen
Das DBMS_PDB.DESCRIBE Package erzeugt ein xml-file der non-CDB, welches anschließend zur Prüfung der PDB-Kompatibilität und zur Erzeugung der neuen PDB verwendet wird.
BEGIN
DBMS_PDB.DESCRIBE(
pdb_descr_file => '/home/oracle/noneCDB.xml');
END;
/
Shutdown non-cdb database
shutdown immediate;
Kompatibilität des Describe-Files durchführen mit CHECK_PLUG_COMPATIBILITY
Das DBMS_PDB.CHECK_PLUG_COMPATIBILITY wird bereits dann in der CDB ausgeführt!
-- connect to CDB$ROOT and run the DBMS_PDB.CHECK_PLUG_COMPATIBILITY function
-- to determine whether the non-CDB is compatible with the CDB
SET SERVEROUTPUT ON
DECLARE
compatible CONSTANT VARCHAR2(3) :=
CASE DBMS_PDB.CHECK_PLUG_COMPATIBILITY(
pdb_descr_file => '/home/oracle/noneCDB.xml',
pdb_name => 'ILTIS')
WHEN TRUE THEN 'YES'
ELSE 'NO'
END;
BEGIN
DBMS_OUTPUT.PUT_LINE(compatible);
END;
/
-- If the output is "YES", then the non-CDB is compatible, and you can continue with the next step.
-- Otherwise check v$PDB_PLUG_IN_VIOLATIONS, fix issues and start again with DBMS_PDB.DESCRIBE (when fixes made in nonCDB) oracle
-- with DBMS_PDB.CHECK_PLUG_COMPATIBILITY check when fixes made in new CDB($ROOT) database
Die PDB_PLUG_IN_VIOLATIONS prüfen und ggf. Fehler fixen
Die PDB_PLUG_IN_VIOLATIONS auf Fehler überprüfen und die Feher beheben. Warnings können ignoriert werden.
set lin 180
set pages 400
col NAME format a30
col MESSAGE format a50
col CAUSE format a20
--
select NAME, TYPE, CAUSE, MESSAGE, STATUS from PDB_PLUG_IN_VIOLATIONS WHERE status <> 'RESOLVED';
Nachdem die Fehler behoben sind, noch einmal dass DBMS_PDB.DESCRIBE ausführen und erneut einen CHECK_PLUG_COMPATIBILITY durchführen. Anschließend wieder die PDB_PLUG_IN_VIOLATIONS überprüfen.
Plug in non-CDB als PDB in die CDB
Die nonCDB als PDB in die CDB pluggen. Achtung bei größeren Datenbanken MOVE
nehmen, sonst werden die Datenfiles kopiert.
CREATE PLUGGABLE DATABASE ILTIS USING '/home/oracle/ILTIS.xml' MOVE;
Die neue Pluggable Database ist dann im Mount Status und darf nicht geöffnet werden. Das kommt erst weiter unten!
Erneut PDB_PLUG_IN_VIOLATIONS prüfen
select NAME, TYPE, CAUSE, MESSAGE, STATUS from PDB_PLUG_IN_VIOLATIONS WHERE status <> 'RESOLVED'order by time desc;
nonCDB zu einer PDB konvertieren
Dieser Schritt ist das eigentliche Convert von einer non-CDB zu einer PDB.
alter session set container=ILTIS;
@$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql
Status der neuen PDB prüfen
set lin 180
set pages 4000
--
select name, open_mode, restricted, open_time, inst_id, con_id, dbid, con_uid from gv$pdbs;
Die neue PDB zum ersten Mal read write öffnen
Die Plugable database das erste mal read write öffnen (wichtig!)
ALTER PLUGGABLE DATABASE OPEN;
Status der neuen PDB prüfen
set lin 180
set pages 4000
--
select name, open_mode, restricted, open_time, inst_id, con_id, dbid, con_uid from gv$pdbs;
select PDB_ID, PDB_NAME, STATUS, LOGGING from CDB_PDBS
Ein abschließdender Blick in das alert.log kann auch nicht schaden 🙂
Quellen
- Release 19 Concepts and Administration Creating a Physical Standby Database
- Learn about reducing downtime during a database migration Learn / About Migrating with Oracle Data Guard
- Oracle Patch Assurance – Data Guard Standby-First Patch Apply (Doc ID 1265700.1)
- Concepts and Administration / Introduction to Oracle Data Guard
- Release 19 / Scenarios Using the DGMGRL Command-Line Interface
- How To Remove Standby Database And Convert It to Standalone Database (Doc ID 2074686.1)
- Upgrading and Converting Non-CDBs to a PDB with the Same Operating System / Adopting a Non-CDB as a PDB