ORA-39405: Oracle Data Pump does not support importing from a source database with TSTZ version 42 into a target database with TSTZ version 32.

David SanzDavid Sanz
4 min read

Hoy vamos a abordar cómo podemos modificar el TSTZ en un entorno Multitenant y en un Single Instance si hemos encontrado el siguiente error al intentar realizar una importación con Datapump:

 ORA-39405: 
  Oracle Data Pump does not support importing from a source database 
    with TSTZ version 42 into a target database with TSTZ version 32.

Este error es debido a que el timezone de ambos entornos no coincide. Pero, ¿Podemos realizar el cambio? SI. Eso si, este cambio no se puede realizar sin una verificación previa, vamos a ello.

Single Instance

Para este tipo de entornos, debemos verificar con DBMS_DST cual es la versión más actual de nuestro timezone. Este package fue implementado por Oracle en la versión 11gR2 con el fin de facilitar los procedimientos de actualización de la zona horaria en nuestras bases de datos.

SELECT DBMS_DST.get_latest_timezone_version From Dual;

GET_LATEST_TIMEZONE_VERSION
---------------------------
                         43

En nuestro caso hemos tenido suerte, ya que la versión coincide con la del entorno de exportación. Sin embargo, ¿qué pasaría si la versión más reciente no coincide? Tendríamos que recurrir al export clásico. Tendríamos que recurrir al export clásico. Este tipo de exportación es un tema diferente que mi compañero de batallas Cele Cueve explica muy bien en su blog. Aquí les dejo el enlace por si desean aprender cómo resolverlo en caso de que no se pueda actualizar:

https://dbaspain.com/2025/03/13/ora-39405-error-tstz-al-hacer-expdp-impdp-otra-forma-de-importar-los-datos/

Si no conocían este blog, les sugiero que lo visiten, ya que publica artículos muy top.

Ahora, vamos a actualizar la zona horaria en el entorno.

Lo primero que vamos hacer es cerrar y abrirla en modo upgrade nuestra base de datos. Una vez abierta, lanzamos el siguiente bloque anónimo para que nuestro entorno este atento de lo que vamos hacer.

SQL> shu immediate
SQL> startup upgrade
SQL>
DECLARE
  l_tz_version PLS_INTEGER;
BEGIN
  l_tz_version := DBMS_DST.get_latest_timezone_version;
  DBMS_OUTPUT.put_line('l_tz_version=' || l_tz_version);
  DBMS_DST.begin_prepare(l_tz_version);
END;
/

Comprobamos que la ejecución del bloque anónimo ha ido bien verificando el parámetro DST_SECONDARY_TT_VERSION. Ahí deberíamos ver la versión a la que vamos a subir.

SELECT property_name, property_value
FROM   database_properties
WHERE  property_name LIKE 'DST_%'
ORDER BY property_name;

PROPERTY_NAME                  PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION         32
DST_SECONDARY_TT_VERSION       43
DST_UPGRADE_STATE              PREPARE

Antes de confirmar el cambio, vamos a verificar si podríamos tener algún problema con los objetos de nuestra base de datos que se verán afectados. Importante, antes de verificar limpiar las siguientes tablas: SYS.DST$AFFECTED_TABLES y SYS.DST$ERROR_TABLE.

SQL> TRUNCATE TABLE sys.dst$affected_tables;
SQL> TRUNCATE TABLE sys.dst$error_table;
SQL> EXEC DBMS_DST.find_affected_tables;
SQL> Select Decode(count(*),0,'SIN_PELIGRO','CUIDADO') from sys.dst$affected_tables;

DECODE(COUN
-----------
SIN_PELIGRO

SQL> select * from sys.dst$error_table;
no rows selected

Finalizamos la fase de preparación (DBMS_DST.END_PREPARE), cerramos y abrimos de nuevo en modo upgrade para confirmar el cambio de timezone.

SQL> EXEC DBMS_DST.end_prepare;
SQL> shu immediate
SQL> startup upgrade
SQL> SET SERVEROUTPUT ON
DECLARE
  l_tz_version PLS_INTEGER;
BEGIN
  SELECT DBMS_DST.get_latest_timezone_version
  INTO   l_tz_version
  FROM   dual;
  DBMS_OUTPUT.put_line('l_tz_version=' || l_tz_version);
  DBMS_DST.begin_upgrade(l_tz_version);
END;
/
l_tz_version=43
An upgrade window has been successfully started.

Al terminar nos devolverá la versión instalada

l_tz_version=43
An upgrade window has been successfully started.

Multitenant

El proceso para actualizar la zona horaria será completamente diferente, ya que debemos llevar a cabo la operación en todos los contenedores. Mike Dietrich lo explica de manera clara en su sitio web.

https://mikedietrichde.com/2018/12/18/how-to-patch-all-pdbs-with-the-a-new-time-zone-file/

Así que vamos a ello.

El primer paso que tenemos que verificar es la versión del timezone:

 alter system set "_exclude_seed_cdb_view"=false scope=both;

 column value$ format a20
 select value$, con_id from containers(SYS.PROPS$) where NAME='DST_PRIMARY_TT_VERSION' order by 2

VALUE$                   CON_ID
-------------------- ----------
32                            1
32                            2
32                            4

Antes de ejecutar la consulta, lo primero que hicimos fue setear el parámetro _exclude_seed_cdb_view a false antes de lanzar la sql.

Un par de apuntes sobre este parámetro:

  • Se recomienda configurarlo en false cuando trabajamos con entornos multitenant.

  • Es un parámetro reservado (empieza por “_”)

  • Si lo configuramos en true, oculta todo lo relacionado con PDB$SEED en las consultas SQL habituales. Veamos un ejemplo, conectándonos a nuestra CDB$Root y consultando el valor del parámetro cuando conectamos por primera vez (también consultaremos las PDBS que tiene nuestro contendor):

SYS> show parameter _exclude_seed_cdb_view
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
_exclude_seed_cdb_view               boolean     FALSE

SYS> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB                            READ WRITE NO

Vamos a ver que nos muestra la consulta anterior con el parámetro a TRUE:

SYS@OSIGBP> alter system set "_exclude_seed_cdb_view"=true scope=both;

System altered.

SYS@OSIGBP> select value$, con_id from containers(SYS.PROPS$) where NAME='DST_PRIMARY_TT_VERSION' order by 2;

VALUE$                   CON_ID
-------------------- ----------
32                            1
32                            3

Muy interesante, podemos observar que la información de PDB$SEED se oculta al setear el valor a true.

Continuamos asegurándonos que tenemos las PDB abiertas

[oracle~]
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -b tzcheck -d $ORACLE_HOME/rdbms/admin -n 1 -l /tmp utltz_upg_check.sql
...
[oracle~]
$ORACLE_HOME/perl/bin/perl $ORACLE_HOME/rdbms/admin/catcon.pl -b tzapply -d $ORACLE_HOME/rdbms/admin -n 1 -l /tmp utltz_upg_apply.sql
...

La primera sentencia sería como un pequeño test pero sin aplicar “tzcheck“, y la segunda sentencia realiza el cambio “tzapply“.

Verificamos:

 column value$ format a20
 select value$, con_id from containers(SYS.PROPS$) where NAME='DST_PRIMARY_TT_VERSION' order by 2

VALUE$                   CON_ID
-------------------- ----------
43                            1
43                            2
43                            4

Listo. Espero que os sirva.

0
Subscribe to my newsletter

Read articles from David Sanz directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

David Sanz
David Sanz

Soy desarrollador, Analista, DBA Oracle y Arquitecto OCI, certificado en OCI Migration and Integration Certified Professional y Certified Architect Associate con más de 15 años de experiencia en plataformas Oracle además de especialista en temas de rendimiento.