Olá pessoal, aqui vai um breve artigo sobre um possível bug que encontrei na migração do Oracle Database 12.2 de nonCDB para PDB. É um problema contornável e aqui também apresento a solução.
Após reportar para o Mike Dietrich (Master Product Manager – Database Upgrades & Migrations), ele levantou a questão junto ao responsável pelo script noncdb_to_pdb.sql e caso necessário será aberto um bug para o caso.
Cenário que encontrei
Para este cenário segui exatamente o artigo do Tim Hall: https://oracle-base.com/articles/12c/multitenant-hot-clone-remote-pdb-or-non-cdb-12cr2
O problema que tive foi por conta de um parâmetro estar com um valor menor do que o Oracle esperava. Vamos ver o que aconteceu…
O objetivo era migrar o banco de dados de nome noncdb1 que estava na versão 12.2.0.1 para um PDB no banco de dados de nome cdb3 também na versão 12.2.0.1.
Depois de configurar o ambiente conforme o artigo do Tim Hall executei os seguintes passos apresentados abaixo…
No banco de dados cdb3:
SQL> CREATE PLUGGABLE DATABASE pdb4 FROM NON$CDB@clone_link; Pluggable database created.
Meu PDB pdb4 foi criado com sucesso a partir do banco de dados noncdb1. Vamos ver o status dos PDBs:
SQL> column name format a30 SELECT d.con_id, p.name, p.open_mode, d.status, TO_CHAR( p.open_time, 'DD/MM/YYYY HH24:MI:SS' ) open_time, p.total_size / 1024 / 1024 total_mb, p.max_size / 1024 / 1024 max_mb, p.local_undo, d.refresh_mode FROM v$pdbs p, dba_pdbs d WHERE p.name = d.pdb_name ORDER BY 1; CON_ID NAME OPEN_MODE STATUS OPEN_TIME TOTAL_MB MAX_MB LOCAL_UNDO REFRES ---------- ------------------ ---------- ---------- ------------------- ---------- ---------- ---------- ------ 2 PDB$SEED READ ONLY NORMAL 28/06/2017 21:51:04 744 0 1 NONE 3 PDB1 MOUNTED NORMAL 0 0 1 NONE 4 PDB4 MOUNTED NEW 28/06/2017 22:08:54 0 0 1 NONE 5 PDB2 READ WRITE NORMAL 28/06/2017 21:51:05 3537 0 1 NONE 6 PDB3 READ WRITE NORMAL 28/06/2017 21:51:05 3902 0 1 NONE Elapsed: 00:00:00.02
Feito isso direcionei a sessão para o novo pdb4:
SQL> alter session set container=pdb4; Session altered. Elapsed: 00:00:00.00
Como já sei do problema verifico o parâmetro job_queue_processes:
SQL> sho parameter job_queue NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ job_queue_processes integer 4000
Vejam que o job_queue_processes está definido com o valor de 4000 para o meu PDB.
Então executei o script de conversão de nonCDB para PDB nesta mesma sessão:
SQL> @?/rdbms/admin/noncdb_to_pdb.sql --...MUITAS LINHAS DE EXECUÇÃO NÃO APRESENTADAS AQUI POR NÃO INFLUENCIAREM NO CONTEXTO APRESENTADO 22:28:29 DOC># 22:28:29 SQL> 22:28:29 SQL> DECLARE 22:28:29 2 threads pls_integer := &&1; 22:28:29 3 BEGIN 22:28:29 4 utl_recomp.recomp_parallel(threads); 22:28:29 5 END; 22:28:29 6 / DECLARE * ERROR at line 1: ORA-20000: Unable to gather statistics concurrently: the job_queue_processes parameter is less than 4 ORA-06512: at "SYS.UTL_RECOMP", line 899 ORA-06512: at "SYS.DBMS_STATS", line 36873 ORA-06512: at "SYS.DBMS_STATS", line 4298 ORA-06512: at "SYS.DBMS_STATS", line 36652 ORA-06512: at "SYS.UTL_RECOMP", line 260 ORA-06512: at "SYS.UTL_RECOMP", line 803 ORA-06512: at line 4 Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production [oracle@oracle-srv ~]$
Observem que o erro retornado no script, após um bom tempo de execução, é referente ao parâmetro estar definido com um valor abaixo de 4, porém conferimos que o parâmetro estava em 4000 antes de executarmos o script. Este erro acontece na etapa de compilação de objetos onde o Oracle tenta executar com paralelismo de 4 e não consegue devido ao valor do parâmetro estar abaixo, mas acredito que isso seja um problema do script, pois não acho que ele deveria esperar um valor exato e ainda assim verificamos que o parâmetro job_queue_processes do pdb4 estava em 4000 antes da execução.
Ao verificar o meu banco de dados noncdb que foi copiado e então convertido nesta migração identifiquei que nele o valor definido para o parâmetro job_queue_processes era 3:
[oracle@oracle-srv ~]$ . oraenv ORACLE_SID = [cdb2] ? noncdb1 The Oracle base remains unchanged with value /u01/app/oracle [oracle@oracle-srv ~]$ sqlplus / as sysdba SQL*Plus: Release 12.2.0.1.0 Production on Wed Jun 28 22:25:18 2017 Copyright (c) 1982, 2016, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production SQL> sho parameter db_name NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_name string noncdb1 SQL> sho parameter job_queue NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ job_queue_processes integer 3
Então em algum momento o Oracle grava o parâmetro antigo e tenta reutilizar nesta conversão.
Para corrigir não é necessário alterar o parâmetro no banco de dados nonCDB e copiá-lo novamente. Vamos ver como resolver depois de migrado.
Vamos ver como o pdb4 ficou agora depois da execução com erro do script:
SQL> column name format a30 SELECT d.con_id, p.name, p.open_mode, d.status, TO_CHAR( p.open_time, 'DD/MM/YYYY HH24:MI:SS' ) open_time, p.total_size / 1024 / 1024 total_mb, p.max_size / 1024 / 1024 max_mb, p.local_undo, d.refresh_mode FROM v$pdbs p, dba_pdbs d WHERE p.name = d.pdb_name ORDER BY 1; CON_ID NAME OPEN_MODE STATUS OPEN_TIME TOTAL_MB MAX_MB LOCAL_UNDO REFRES ---------- ------------------------------ ---------- ---------- ------------------- ---------- ---------- ---------- ------ 2 PDB$SEED READ ONLY NORMAL 28/06/2017 21:51:04 744 0 1 NONE 3 PDB1 MOUNTED NORMAL 0 0 1 NONE 4 PDB4 READ WRITE NEW 28/06/2017 22:28:18 3000 0 1 NONE 5 PDB2 READ WRITE NORMAL 28/06/2017 21:51:05 3537 0 1 NONE 6 PDB3 READ WRITE NORMAL 28/06/2017 21:51:05 3902 0 1 NONE Elapsed: 00:00:00.02
Vejam que o pdb4 está em modo read write, isso porque durante a execução do script o mesmo executa um “open upgrade” no PDB.
Vamos ver como está o parâmetro:
SQL> alter session set container=pdb4; Session altered. Elapsed: 00:00:00.05 SQL> sho parameter job_queue NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ job_queue_processes integer 3
O parâmetro agora está definido com o valor 3. Vamos alterar para 4 e baixar o pdb4 deixando-o em modo mount:
SQL> alter system set job_queue_processes=4; System altered. Elapsed: 00:00:00.03 SQL> alter pluggable database close; Pluggable database altered. Elapsed: 00:00:01.74
Agora reexecutamos o script noncdb_to_pdb.sql:
SQL> show con_name CON_NAME ------------------------------ PDB4 SQL> @?/rdbms/admin/noncdb_to_pdb.sql -- MUITAS LINHAS AQUI, MAS O SCRIPT FINALIZA SEM ERROS...
Desta vez ele finaliza com sucesso, sem erros.
Vamos então abrir o pdb4 e finalizar o processo de migração de nonCDB para PDB:
SQL> sho con_name CON_NAME ------------------------------ PDB4 SQL> select open_mode from v$pdbs; OPEN_MODE ---------- MOUNTED 1 row selected. Elapsed: 00:00:00.01 SQL> alter pluggable database open; Pluggable database altered. Elapsed: 00:00:11.49
PDB aberto com sucesso.
Na view PDB_PLUG_IN_VIOLATIONS podemos verificar que o erro na execução do script noncdb_to_pdb.sql está com o status “RESOLVED”, mas ainda temos um warning que é referente aos serviços que existian no banco de dados noncdb1:
SQL> select * from PDB_PLUG_IN_VIOLATIONS; TIME NAME CAUSE TYPE ERROR_NUMBER LINE MESSAGE STATUS ACTION CON_ID ------------------------------ ----- ------------------------------ --------- ------------ ---------- -------------------------------------------------- --------- ------------------------------ ---------- 28-JUN-17 11.00.36.534704 PM PDB4 Non-CDB to PDB ERROR 0 1 PDB plugged in is a non-CDB, requires noncdb_to_pd RESOLVED Run noncdb_to_pdb.sql. 4 b.sql be run. 28-JUN-17 11.00.36.760384 PM PDB4 Service Name Conflict WARNING 0 1 Service name or network name of service noncdb1XDB in PENDING Drop the service and recreate 4 the PDB is invalid or conflicts with an existing it with an appropriate name. service name or network name in the CDB. 2 rows selected. Elapsed: 00:00:00.00
Para remover estes serviços podemos consultar:
SQL> select name from dba_services; NAME ------------------------------ noncdb1XDB noncdb1 pdb4.localdomain 3 rows selected. Elapsed: 00:00:00.00
Como estamos conectados no pdb4, não deve haver serviços chamados ‘%cdb%’. Vamos então removê-los:
SQL> exec dbms_service.delete_service('noncdb1XDB'); PL/SQL procedure successfully completed. Elapsed: 00:00:00.06 SQL> exec dbms_service.delete_service('noncdb1'); PL/SQL procedure successfully completed. Elapsed: 00:00:00.01
E então reinicio novamente o pdb4 para verificar o novo status da view PDB_PLUG_IN_VIOLATIONS:
SQL> alter pluggable database close; Pluggable database altered. Elapsed: 00:00:00.41 SQL> alter pluggable database open; Pluggable database altered. Elapsed: 00:00:01.40
Consulto novamente a view e identifico que os erros e alertas estão todos resolvidos:
SQL> select * from PDB_PLUG_IN_VIOLATIONS; TIME NAME CAUSE TYPE ERROR_NUMBER LINE MESSAGE STATUS ACTION CON_ID ------------------------------ ------------------------------ ------------------------------ --------- ------------ ---------- -------------------------------------------------- --------- ------------------------------ ---------- 28-JUN-17 11.00.36.534704 PM PDB4 Non-CDB to PDB ERROR 0 1 PDB plugged in is a non-CDB, requires noncdb_to_pd RESOLVED Run noncdb_to_pdb.sql. 4 b.sql be run. 28-JUN-17 11.08.37.826200 PM PDB4 Service Name Conflict WARNING 0 1 Service name or network name of service noncdb1XDB in RESOLVED Drop the service and recreate 4 the PDB is invalid or conflicts with an existing it with an appropriate name. service name or network name in the CDB. 2 rows selected. Elapsed: 00:00:00.02
Solução de contorno proposta pelo Mike
Depois de falar com o Mike Dietrich ele testou diversas vezes e informou outra solução de contorno: desabiltar as estatísticas concorrentes no PDB em questão.
Para desabilitar execute:
SQL> EXEC DBMS_STATS.SET_GLOBAL_PREFS('CONCURRENT','FALSE'); PL/SQL procedure successfully completed.
Bom pessoal, por hoje é isso. Espero que ajude quando tiverem que fazer este tipo de migração.
Abraços,
Franky