ORA-39405 Error TSTZ al hacer expdp/impdp. Otra forma de importar los datos

Estoy completamente seguro que el 90% de los DBAs existentes en el planeta tierra se han encontrado con este error alguna vez.
Al igual que yo, te has puesto a buscar alternativas, soluciones, parches, workarounds, algún truco que alguien haya publicado por la red, a ver si consigues llevar a cabo la tarea que te han encomendado.
En los últimos días he leído mucho sobre este tema. He leído artículos que cuentan desde las soluciones más aconsejables y completas hasta las más descabelladas. Por ejemplo actualizar o parchear la base de datos donde no puedes importar los datos o copiar la librería de timezone de una base de datos a otra, y rezarle a todo lo que sepas para que la importación vaya bien y no crear una corrupción de datos o provocar un estallido de la base de datos. ¿Crees que sabes cual es la aconsejable y cual la descabellada?
En mi caso concreto, no podía hacer trucos de magia y jugármela. Tampoco podía ni me permitían actualizar o parchear con un nuevo Release Update la base de datos destino para tener el mismo nivel de timezone y poder realizar la importación correctamente.
Al final he podido importar los datos, usando una utilidad de toda la vida, pero en la que quizá nunca hubiera caído en usar de no ser por un amigo y compañero de profesión que me dio la clave.
¿Quieres que te cuente el secreto? Acompáñame en esta historia.
Contexto
Te pongo en situación para entender de donde partimos.
Tenemos dos bases de datos, en distintos servidores.
Origen: Servidor Solaris / Base de Datos Oracle 19.23
Destino: Servidor Linux / Base de Datos Oracle 19.8
El Error
[oracle@servidor1 ]$ impdp "/ as sysdba" directory=IMP logfile=import_timezone.log schemas=DEMO dumpfile=import_timezone.dmp
Import: Release 19.0.0.0.0 - Production on Tue Mar 11 14:33:39 2025
Version 19.8.0.0.0
Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
ORA-39002: operacion no valida
ORA-39405: El pump de datos de Oracle no soporta la importacion de una base de datos de origen con la version 43 de TSTZ a una base de datos de destino con la version 32 de TSTZ.
¿Por qué ocurre esto? ¿Por qué nos aparece el error de timezone?
Este error ocurre cuando la versión de timezone del destino es inferior a la versión de timezone del origen. Podemos consultar esta información con la siguiente consulta:
SELECT * FROM V$TIMEZONE_FILE;
También, puedes consultar si hay disponible una versión superior a la que puedas actualizar.
SELECT DBMS_DST.GET_LATEST_TIMEZONE_VERSION FROM DUAL;
Para entenderlo un poco mejor, vamos a verlo con un ejemplo.
- Origen:
SQL> SELECT * FROM V$TIMEZONE_FILE;
FILENAME VERSION CON_ID
-------------------- ---------- ----------
timezlrg_43.dat 43 0
- Destino:
SQL> SELECT * FROM V$TIMEZONE_FILE;
FILENAME VERSION CON_ID
-------------------- ---------- ----------
timezlrg_32.dat 32 0
Esta librería se puede localizar en la siguiente ruta. (No quiero incitarte a que cambies el fichero por otro que te venga mejor).
$ORACLE_HOME/oracore/zoneinfo/timezlrg_43.dat
Como puedes ver, en el origen tenemos la versión 43, y en el destino una versión inferior, la versión 32. El mensaje de error nos lo indica igualmente muy claro.
Posibles soluciones
1. Actualizar la base de datos o aplicar un nuevo RU.
En mi opinión, la mejor solución y la más fiable es la de aplicar un Release Update a la base de datos, que actualice la versión de timezone y poder realizar cualquier acción con seguridad.
En caso de que tras aplicar el parche y subir la versión de la base de datos no se actualice el timezone, te dejo aquí la forma de actualizar solo este componente, de la mano de Tim Hall.
Upgrade the Database Time Zone File Using the DBMS_DST Package
2. Sustituir los ficheros de timezone desde el sistema operativo (NO RECOMENDADO)
Como ya dejé caer anteriormente, hay quien ha falseado los ficheros de timezone por una versión más reciente, cosa que él mismo no recomienda y no aconseja hacerlo, pero en alguna ocasión, le ha salvado del apuro.
Este «truco» lo he podido ver en el blog de Ora.Ninja
Mi Solución
Comentando esta situación con un compañero de profesión con el que a veces hacemos coworking matutino, vespertino o cuando se presenta, me sugirió probar una utilidad que aunque está en desuso, ahí sigue estando, y en esta ocasión, nos ha aportado solución a nuestro problema.
Te hablo de la utilidad exp. Si, si, exp, nada de expdp. El antiguo exp, a secas, sin datapump.
Esta utilidad tiene de bueno que no tiene en cuenta el timezone, pero también tiene sus limitaciones e inconvenientes. Por ejemplo, el principal inconveniente que yo he encontrado es que no admite algunos tipos de datos, que cada vez son más comunes.
Algunos tipos de datos que exp NO puede exportar correctamente
- CLOB y BLOB grandes (superiores a 64 KB): exp tiene problemas con lobs grandes y no los maneja de manera eficiente.
- BFILE: Los archivos físicos del SO referenciados por BFILE no se exportan porque exp solo almacena la ruta del archivo, no su contenido.
- XMLType: Solo exporta este tipo de dato cuando es almacenado como CLOB.
- TDE: exp no exporta correctamente los datos encriptados con Transparent Data Encryption.
En la tarea que yo tenía que realizar, tenía que mover un esquema pequeñito. El esquema tenía pocos objetos, y además, eran objetos creados con la aplicación ODI en una versión también antigua, por lo que es posible que nos sirviera.
Comprobé los tipos de segmentos que tenía en origen y no me lo pensé.
SQL> select owner, segment_type from dba_segments where owner='ESQUEMA_DEMO' group by owner, segment_type
OWNER SEGMENT_TYPE
---------------- ------------------
ESQUEMA_DEMO INDEX
ESQUEMA_DEMO LOBSEGMENT
ESQUEMA_DEMO TABLE
ESQUEMA_DEMO LOBINDEX
Ejecuté el export en origen de la siguiente manera:
servidor1:/oracle/temp $ export NLS_LANG=.WE8ISO8859P15
servidor1:/oracle/temp $ exp " '/ as sysdba' " owner=ESQUEMA_DEMO FILE=exp_demo.dmp LOG=log_exp_demo.log
Importante indicarle el NLS_LANG que usa tu base de datos, para que no coja otro distinto por defecto, y empiecen a aparecer errores de caracteres y también de estadísticas de este tipo:
EXP-00091: Exporting questionable statistics.
Una vez tenemos el export terminado, lo pasamos a destino y lo importamos:
[oracle@servidor2 ]$ export NLS_LANG=.WE8ISO8859P15
[oracle@servidor2 ]$ imp " '/ as sysdba' " FROMUSER=ESQUEMA_DEMO TOUSER=ESQUEMA_DEMO19 FILE=exp_demo.dmp LOG=log_imp_demo19.log STATISTICS=none
En el ejemplo te pongo como se haría con un remap schema, si quieres importarlo con otro nombre. Lo que no se puede hacer es un remap de tablespace, por lo que será necesario que los tablespces los crees antes de ejecutar el imp.
Al finalizar la importación, comprobé el tipo y cantidad de objetos que había dentro del esquema, por si había alguna diferencia.
-- ORIGEN
SQL> col owner for a25
col object_type for a20
select owner, object_type, count(1) total
from dba_objects
where owner = '&owner'
group by owner, object_type
order by owner, object_type;
Enter value for owner: ESQUEMA_DEMO
old 3: where owner = '&owner'
new 3: where owner = 'ESQUEMA_DEMO'
OWNER OBJECT_TYPE TOTAL
------------- ------ -------------------- ----------
ESQUEMA_DEMO INDEX 922
ESQUEMA_DEMO LOB 124
ESQUEMA_DEMO PROCEDURE 1
ESQUEMA_DEMO TABLE 187
ESQUEMA_DEMO VIEW 75
-- DESTINO
SQL> col owner for a25
col object_type for a20
select owner, object_type, count(1) total
from dba_objects
where owner = '&owner'
group by owner, object_type
order by owner, object_type;
Introduzca un valor para owner: ESQUEMA_DEMO19
antiguo 3: where owner = '&owner'
nuevo 3: where owner = 'ESQUEMA_DEMO19'
OWNER OBJECT_TYPE TOTAL
------------------------- -------------------- ----------
ESQUEMA_DEMO19 INDEX 922
ESQUEMA_DEMO19 LOB 124
ESQUEMA_DEMO19 PROCEDURE 1
ESQUEMA_DEMO19 TABLE 187
ESQUEMA_DEMO19 VIEW 75
Finalmente, todo se había importado bien, y la aplicación ODI conectó correctamente con este esquema. Las pruebas que se realizaron fueron satisfactorias y con esta utilidad, hemos conseguido salvar este problema que nos impedía tener todos los esquemas de esta aplicación en la misma base de datos.
Si alguna vez tienes problemas de timezone con datapump, recuerda que exp es tu amigo y te puede ayudar en algunos casos. 🙌🏼