ORA-39405: El pump de datos de Oracle no soporta la importación de una base de datos de origen con la versión XX de TSTZ a una base de datos de destino con la versión XX de TSTZ

El ORA-39405 nos lo podemos encontrar al lanzar un import o impdp procedente de otra base de datos y es producido una diferencia en la versión del timezone (TSTZ) entre la base de datos origen y destino.

Podemos comprobar la versión del timezone que tenemos en ambas máquinas con este comando:

SQL> SELECT * FROM v$timezone_file;

Solución al ORA-39405

Teóricamente, la máquina donde estamos lanzando el import tendrá una versión inferior del timezone de la máquina origen, así que si queremos continuar con la importación no nos quedará otra que actualizar.

Para ello lanzamos el siguiente comando que nos devolverá la versión más actual del timezone que podemos instalar en nuestra base de datos:

SELECT DBMS_DST.get_latest_timezone_version
 FROM dual;

Si coincide con la versión del error, procedemos a actualizar la base de datos. Lo primero que tendremos que hacer es apagar y arrancar en modo upgrade:

SHUTDOWN IMMEDIATE;
STARTUP UPGRADE;

Lanzamos el siguiente procedimiento, que preparará la base de datos para la actualización:

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 actualización esté preparada revisando el parámetro DST_SECONDARY_TT_VERSION. Ahí debería aparecer la nueva versión que queremos instalar.

COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20

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

Buscamos las tablas que se verán afectadas por la actualización, por si tuviésemos algún problema. En mi caso nunca ha habido problema y, por experiencia propia, no deberían aparecer tablas:

EXEC DBMS_DST.find_affected_tables;
select count(*) from sys.dst$affected_tables;
select * from sys.dst$error_table;

Terminamos de preparar la base de datos con este comando:

EXEC DBMS_DST.end_prepare;

Y reiniciamos para proceder con la instalación:

SHUTDOWN IMMEDIATE;
STARTUP UPGRADE;

Lanzamos lo siguiente:

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;
/

Al terminar nos devolverá la versión instalada, diciendo algo tal que así «l_tz_version=32 An upgrade window has been successfully started«.

Vamos ya con los últimos pasos, apagamos la base de datos y la arrancamos de forma normal:

SHUTDOWN IMMEDIATE;
STARTUP;

Y lanzamos el siguiente procedimiento:

SET SERVEROUTPUT ON
DECLARE
  l_failures   PLS_INTEGER;
BEGIN
  DBMS_DST.upgrade_database(l_failures);
  DBMS_OUTPUT.put_line('DBMS_DST.upgrade_database : l_failures=' || l_failures);
  DBMS_DST.end_upgrade(l_failures);
  DBMS_OUTPUT.put_line('DBMS_DST.end_upgrade : l_failures=' || l_failures);
END;
/

Nos devolverá la lista de tablas afectas y el número de fallos que ha tenido (insisto, por norma general deberían aparecer 0 errores) y ya podemos comprobar la nueva versión del timezone:

SELECT * FROM v$timezone_file;
COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20

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

Ahora podremos lanzar el import o impdp sin que nos de ningún tipo de problema.

¿Qué hacer si la versión de timezone_file ya está en la última versión disponible?

Personalmente me he encontrado alguna vez en la situación de que, tras lanzar la comprobación para instalar la última versión del timezone, no hay ninguna disponible puesto que ya la base de datos en cuestión ya está en la última versión disponible para esa instalación o ese tipo de base de datos.

Esto que voy a explicar ahora mismo no es recomendable y no debería hacerse pero como a mi me ha servido y me ha salvado del apuro, os lo voy a explicar.

Si os pide una versión superior del timezone, que no deja instalar en la máquina destino (esto seguramente se deberá a que son máquinas distintas o el tipo de base de datos es diferente) podemos copiar los ficheros de timezone de la versión XX de la máquina origen a la máquina destino y actualizarlos. Repito, esto no debería hacerse y si lo haces, hazlo bajo tu cuenta y riesgo, como último recurso.

Estos ficheros están en la ruta

$ORACLE_HOME/oracore/zoneinfo

En uno de los casos con los que me he encontrado, la máquina origen tenía la versión 34 y la destino la 32, por ello obtuve el ORA-39405. En dicho caso me fui a la ruta y me llevé los ficheros de la versión 34, para copiarlos en la misma ruta de la máquina destino. Los ficheros siempre serán dos y tendrán un nombre parecido a éste:

timezlrg_34.dat
timezone_34.dat

El número de versión puede variar en vuestro caso. Una vez copiados dichos ficheros podemos ejecutar el procedimiento que detallo más arriba y aplicar esta versión que acabamos de copiar.

3 comentarios en «ORA-39405: El pump de datos de Oracle no soporta la importación de una base de datos de origen con la versión XX de TSTZ a una base de datos de destino con la versión XX de TSTZ»

  1. Muchísimas gracias por el artículo! Muy bien explicado, me ha complementado excelente con la nota del MOS sobre aplicación del parche para instalar la DSTv36. Lo coloco acá por si alguien requiere mayores referencias:

    – Applying the DSTv36 update for the Oracle Database (Doc ID 2767770.1)

    Me ha funcionado sobre una Oracle 19c que presentaba el error «ORA-39405: Oracle Data Pump does not support importing from a source database with TSTZ version 36 into a target database with TSTZ version 32.»

    Saludos!

    Responder

Deja un comentario