Resolvendo o ORA-39405 em um Ambiente Multitenant

Quando realizamos operações de importação de dados via Oracle Data Pump, podem existir casos onde o banco de destino dos dados, no qual está sendo realizada a importação, e o banco de origem, de onde os dados foram exportados, possuem a versão de seu arquivo de time zone em versões diferentes.

Caso o banco que realizou a exportação tenha uma versão menor que o banco que realizará a importação, nenhum problema é alertado, e o procedimento de importação ocorre normalmente. O problema ocorre quando tentamos importar um dump file que foi gerado em um banco com versão de arquivo de time zone superior ao que está sendo usado pelo banco de destino. Nesse caso o erro ORA-39405 irá ocorrer;

O cenário

Foi realizada a exportação de um schema de um PDB de um banco CDB, com o intuito de realizar a importação dos dados em um PDB de outro CDB.

O PDB onde foi realizada a exportação estava rodando com um timezone file na versão 36, enquanto que o CDB destino, bem como seus PDBs, estavam rodando na versão 32. Durante a tentativa de import o seguinte erro foi levantado:

A solução

Para este caso, existem duas possibilidades: realizar a aplicação do patch DST (DSTv36, neste caso) referente à versão igual ou superior ao timezone file do banco de origem ou a aplicação da RU que traga uma versão do arquivo de timezone atualizada. Em seguida se faz necessária a atualização do timezone file.

Para este troubleshooting estaremos seguindo com a primeira opção, aplicando o patch DSTv36.

Passo a passo

Validação

Inicialmente realizamos a validação das versões dos timezone files no banco destino, tanto no CDB$ROOT quanto no PDB destino, utilizando a tabela interna PROPS$:

Também podemos realizar esta validação através da V$TIMEZONE_FILE. Além disso, podemos verificar a maior versão de timezone file disponível através da função “get_latest_timezone_version” da package DBMS_DST:

Como a última versão disponível do timezone file não é superior à versão atual, necessitamos aplicar o patch de uma versão igual ou superior à desejada para realizar o upgrade.

Sendo assim, realizamos o download da versão atualizada do OPatch (patch 6880880) e do patch DSTv36 (patch 32327201), ambos para o diretório “/home/oracle/patches/”.

Atualizando o OPatch

Para a atualização do OPatch, navegamos até o Oracle Home do banco que estaremos realizando o procedimento, e renomeamos o diretório OPatch atual, para caso a nova versão apresente algum problema, possamos reverter a mudança:

$ cd $ORACLE_HOME/
$ mv OPatch OPatch_old

Na sequência extraímos o arquivo zipado que contém a versão atualizada do OPatch para este diretório:

$ unzip -q /home/oracle/patches/p6880880_190000_Linux-x86-64.zip

Neste momento o OPatch está atualizado. Podemos validar a nova versão com:

$ ./OPatch/opatch version

Aplicando o patch DSTv36

Primeiramente, o patch foi extraído para o diretório /home/oracle/patches/:

$ cd /home/oracle/patches
$ unzip -q p32327201_190000_Linux-x86-64.zip

Com o patch descompactado, verificamos se existem possíveis conflitos do patch a ser aplicado com os patches já aplicados no Oracle Home destino, através do comando:

$ ./opatch prereq CheckConflictAgainstOHWithDetail -ph /home/oracle/patches/32327201/

Como o retorno do comando não acusa qualquer conflito, seguimos com a aplicação do patch:

$ ./opatch apply /home/oracle/patches/32327201/ -oh $ORACLE_HOME

Com o patch aplicado, podemos verificar que agora a versão mais atual disponível é a 36:

Atualização do timezone file

Para a atualização do timezone file, utilizamos os scripts “utltz_upg_check.sql” e “utltz_upg_apply.sql”, disponibilizados juntamente com o banco de dados no diretório $ORACLE_HOME/rdbms/admin.

Como estamos em um ambiente multitenant, e desejamos atualizar ambos os containers, CDB$ROOT e ORCLPDB, precisamos rodar ambos os scripts em ambos os containers.

A fim de tornar essa operação menos trabalhosa, a Oracle disponibiliza, desde a versão 12.1 do Oracle Database, um utilitário Perl chamado catcon.pl. Ele permite automatizar a execução de scripts SQL em diversos containers ao mesmo tempo.

Para a sua execução, vamos adicionar o Perl disponibilizado pela Oracle nas variáveis de ambiente:

$ export PATH=$PATH:$ORACLE_HOME/perl/bin

E em seguida vamos rodar o script “utltz_upg_check.sql”, usando o catcon.pl:

$ perl $ORACLE_HOME/rdbms/admin/catcon.pl -l /home/oracle/patches/ -b log_check -d $ORACLE_HOME/rdbms/admin utltz_upg_check.sql

Onde:

  • -l : indica o diretório onde serão escritos os logs da operação;
  • -b: o prefixo dos logs;
  • -d: o diretório onde está o script;

Por padrão o catcon.pl roda em paralelo os scripts para todos os containers, porém, caso necessário, podem ser especificados containers para execução (com o parâmetro -c) ou containers onde a execução não ocorrerá (com o parâmetro -C).

Em seguida, rodamos o script “utltz_upg_check.sql”, utilizando o utilitário:

$ perl $ORACLE_HOME/rdbms/admin/catcon.pl -l /home/oracle/patches/ -n 1 -b log_apply -d $ORACLE_HOME/rdbms/admin utltz_upg_apply.sql

Neste ponto, é fundamental a adição do parâmetro “-n 1”. Este parâmetro indica a quantidade de workers, ou seja, de execuções em paralelo ocorrem. Como o script “utltz_upg_check.sql” reinicializa o banco para a atualização do timezone file, caso não seja indicado esse parâmetro, o processo de atualização no PDB pode não finalizar a tempo, antes do banco reinicializar, o que fará com que a atualização no PDB falhe, e depois precise ser feita manualmente. Com o valor setado para 1 (um) o processo ocorrerá sequencialmente.

Após a execução, podemos verificar que nosso timezone file foi atualizado:

Concluindo

Após o patch aplicado e o timezone file atualizado, realizar a importação sem maiores problemas, uma vez que o banco origem, aquele que realizou a exportação dos dados, quanto o destino, aquele que realizará a importação dos dados, estão na mesma versão de timezone file.

Publicar comentário