Cuando estamos removiendo las tripas de la base de datos, hay muchos errores de Oracle que te dan bastantes quebraderos de cabeza. Uno de los que mas trabajo me ha dado en los últimos tiempos ha sido el ORA-03106. La descripción es bastante confusa: «Fatal two task communication protocol error» dice. Y… pueden ser muchas cosas las que provocan este error.
Contenidos
Qué dice el soporte de Oracle sobre ORA-03106
Lo primero que hago cuando me aparece un error en Oracle es dirigirme a la fuente de conocimiento, al soporte, para ver la causa del problema. El soporte es bastante interesante, porque no solo da posibles causas de cada error, sino que también da posibles soluciones.
El problema de ORA-03106 es que, no solo la descripción es algo confusa, las causas que dan soporte y otros usuarios, también lo son. Bastante indeterminadas, pocas soluciones, y no están claras. Al menos para mí personalmente, no he encontrado nada claro.
En algunos foros he leído algunos problemas de este tipo que parece que han quedado sin resolver, o las soluciones propuestas no han resuelto. Debe ser curioso este ORA-03106.
Y aquí la solución que la documentación de Oracle nos aporta cuando encontremos este error:
ORA-03106 fatal two-task communication protocol error
Cause: The communication path between Oracle and the user task has stopped. This is an internal error message not usually issued.
Action: Contact Oracle Support Services.
Si estamos en producción, con licencia y soporte, solo tenemos que hacer uso del contrato de soporte y contactar a Oracle para que nos ayude.
Otra opción, si estamos en desarrollo, es investigar un poco mas en foros, docs, faq y nuestras propias pruebas. La clave está en «This is an internal error message not usually issued.«.
Posibles causas y soluciones
Las posibles causas que la literatura en internet y páginas especializadas, además del soporte y foros de Oracle, dan para este error ORA-03106 incluyen lo siguiente:
Incompatibilidad entre versiones y configuración regional
Incompatibilidades entre las versiones del cliente con el que se accede a la base de datos, y el SGBD. Por ejemplo, que estuviésemos accediendo a un servidor con Oracle 10g a través de un cliente Oracle 11g. Esto puede provocar que el cliente intente acceder o ejecutar características o funciones que el SGBD no tiene.
Soluciones
- Revisar que las versiones de cliente y servidor son las mismas, en caso contrario, instalar el cliente correspondiente a la versión del servidor.
- Comprobar que la configuración regional de cliente y servidor coinciden. Esta es una de las causas mas frecuentes del ORA-03106. Esto lo podremos comprobar lanzando:
show parameters nls
O bien a través de la vista:
select * from v$nls_parameters;
DBLink
Problemas de versiones incompatibles, comunicaciones, red, o cualquier otro, cuando se está usando DBlink.
Un Database link es un acceso remoto a una base de datos externa. No suele ser recomendable por los problemas que puede ocasionar, pero ejemplo de uso mas típico es una mezcla de datos de dos sistemas distintos. Si cada uno tiene su base de datos, un join de una tabla de nuestra BD con la de una BD remota, es posible con un DBlink a la remota. Por poner un ejemplo real en mi experiencia profesional en el ámbito de la sanidad, desde el HIS se obtenía información de explotación de Hospital de Día, y la administración estaba en un departamental con su propia base de datos no integrada. Un DBLink consiguió en una sola select obtener datos merge de ambos sistemas.
Un ejemplo de creación:
CREATE [PUBLIC] DATABASE LINK Nombre
CONNECT TO usuario INDENTIFIED BY contraseña
USING 'alias_bd_remota';
Soluciones
Aquí la solución radical que propone Oracle es que no uses DBLink. Como alternativa al uso de un Database Link tenemos algunas opciones, por ejemplo una réplica, o un proceso cron de carga. Todo puede generar problemas, de un tipo o de otro, como posibles semáforos, inconsistencia de lectura (en sucio) o bloqueos. Todos mas o menos resolubles, afortunadamente.
En cualquier caso no está de más, si es posible, revisar el log y traza del servidor Oracle, con el objetivo de buscar el ORA-03106 y ver qué pone antes o después. Nos puede dar una pista. Y habría que buscar en las trazas de ambos servidores/base de datos.
Problemas de red o de SQL*Net
Así sin mas información, poco podemos hacer mas que revisar la conectividad, que no debería ser si ya estábamos lanzando querys.
Revisar el fichero de configuración sqlnet.ora, que estará ubicado en la ruta base ORA_HOME\network\admin donde también tenemos el tnsnames.ora.
Aquí lo único que suelo encontrar con problemas está en estos valores, pero no conseguiría encontrar el servidor, o conectar, encontrando un ORA-12638: Recuperación de credenciales fallida:
NAMES.DIRECTORY_PATH= (EZCONNECT, LDAP, TNSNAMES, HOSTNAME)
NAMES.DEFAULT_DOMAIN = ORACLE.COM
SQLNET.AUTHENTICATION_SERVICES = (NTS)
Soluciones
Ensayo/error o revisar la configuración correcta de SQL*Net, y revisar las trazas para encontrar alguna descripción de error que pueda llevarnos al problema.
Sí es una buena práctica revisar las rutas de red, delays entre nodos intermedios (si los existiera), en el caso de que nos encontrasemos fuera de la red del servidor (lanzar un Tracert)
Errores en el bloque PL/SQL ejecutado
Un error de programa en nuestro código puede hacer saltar este error Oracle. Se propone revisar parámetros, cabeceras, etc, si es que estamos lanzando un bloque PL/SQL.
Soluciones
Debug de nuestro código, sobre todo si hemos algún cambio en el interfaz y se está consumiendo por algún trigger u otro objeto de nuestra base de datos. Comentar código, buscar, depurar. Es mas corriente de lo que puede parecer.
Memoria SGA corrupta
Poco podríamos hacer aquí. Lo que nos dice es que puede haber un segmento de la memoria compartida que se está usando que esté deteriorado o corrupto. La única solución, en ese caso, pasa por abortar y reiniciar el SGBD. Antes, asegurarnos que los procesos de Oracle que hacen de semáforos de concurrencia y los procesos en background estén parados (pmon, smon, shadow processes, etc)
Soluciones
Acudir al DBA para revisar lo comentado arriba.

Mi caso particular: JDBC, Batch, BLOB, Nologging, Direct Path Insert…
Primer error: Autocast de valor null
Me encontraba yo creando unas ETL para cargar datos en un Datawarehouse, y este molesto error comenzó a aparecer. Tras mucho buscar, el problema, efectivamente, estaba en mi código.
Al final es una causa bastante común, parece, por lo que no está de sobra revisar siempre el código como primera opción. Si es cierto que, sólo revisando código no es fácil encontrar la causa.
El problema, que confirmo que pude resolver, estaba en un autocast de enteros con valor nulo. Me explico, en un bloque PL/SQL estaba considerando un cast a números de varios valores, entre los que estaban algunas columnas con valor nulo. Algo así:
Select nhc as numerohc, ... ,to_number(null) as accesionNumber from vista;
Claro que, existían otros factores que podían influir, como que «vista» era una vista sobre un database link desde Oracle 11 a Oracle 10.
Se resolvió haciendo un casting directo, cambiando to_number (null) por cast(null as number).
Segundo error: Autocast de valor null, otra vez, pero en JDBC.
Dicen que el ser humano es el único animal que cae dos veces en la misma piedra. Esto me hace sospechar que no soy un replicante.
En este caso, estaba traspasando datos para una migración desde Informix a Oracle, y comenzó a salir este viejo amigo llamado ORA-03106. La experiencia sirve, sobre todo, para encontrar mas ágilmente, las minas que he dejado en el código involuntariamente. Así que, recordando el error anterior, fui a buscar los posibles casting de valores nulos. Y ahí estaban, en código Java, y en dos formas distintas.
Una, mas vergonzante, estaba en un casting directo de String a Integer, que no falló en miles de registros, porque recogía un numérico en origen, formateado a String. Pero llegó un registro con valor nulo, y el error 3106 apareció.
Parecía resuelto, pero volvió a salir en otra iteración, y esta vez no había String, pero el driver de Informix devolvía un nulo, que JDBC intentaba convertir a integer con el dichoso error. Se resolvió, aunque han quedado mis dudas de que esto no sea un bug de la versión de JDBC que usé. Por falta de tiempo no investigué mas, una vez resuelto fácilmente, y quedando el código mas completo al no convertir nulos a ceros. En JDBC el método setInt de un statement se convierte a valor 0 cuando el valor es nulo.
Solución: No castear tipos cuando un numérico es null, y usar el método setNull(java.lang.integer).
Tercer error: Bug en Oracle Server Enterprise Edition 10.2.0.1
Este caso fue mas complejo, en una aplicación desarrollada sobre PowerBuilder 8, que usaba la librería OCI para la conexión con Oracle DB, aparecía este error.
El error se producía al hacer un fetch sobre un cursor, donde, en esta ocasión, no estábamos haciendo autocast de tipos. Tras mucho investigar, encontramos que se trataba de un bug ya reportado en la versión de Oracle sobre la que trabajábamos: Oracle EE 10.2.0.1.
Oracle BUG 4523125
Symptoms: OCI based application intermittently throws ORA-03106: fatal two-task communication protocol error. ORA-3106 if cursor flushed between executions
Solution: Upgrade patch Oracle Server 10.2.0.3
Y así se resolvió, el DBA puso el parche, y vino la solución.
Cuarto ORA 03106 error: Hints con Blob grandes.
En esta ocasión, el proceso de Extracción-Transformación-Carga lo implementé en Java, utilizando JDBC. Revisé mis notas sobre este error, e hice los cambios correspondientes en JDBC.
Sin embargo, este error había estado saliendo en el proceso de carga de varias tablas. Cambiando el casting de nulos en tipos enteros desapareció de algunas tablas, sin embargo en otras seguía ocurriendo.
En este caso, la carga de millones de registros me llevó a optimizar la carga de datos en Oracle para evitar tiempos inasumibles, y utilicé las formas que explico en el artículo Optimización de carga de datos en oracle.
Tuve que emplear unas cuantas horas para resolverlo, y lo mas triste, es que me quedé sin saber realmente cual era el problema. Ante la falta de información, no generaba nada en las trazas, comencé a probar, ensayo y error.
Posible causa: Hint Append_Values sobre tablas con blob extensos
Finalmente, el error desapareció de aquellas tablas con campos tipo BLOB, simplemente quitando el Hint Append. Esto me decepcionó bastante, puesto que el tiempo de carga se multiplicó casi por dos al quitar este Hint, pero se completó al 100%.
No he encontrado información al respecto en ningún faq ni soporte de Oracle, por eso decidí dejarlo por escrito en este blog, por si a alguien podía servir para evitar muchas horas de investigar.