viernes, 2 de abril de 2010

Registro dinámico de servicios y ora-12514

En algunas ocasiones he sido consultado sobre problemas de conectividad que se presentan sin previo aviso y vienen acompañados del mensaje de error ORA-12514: TNS:listener does not currently know of service requested in connect descriptor. Hay quienes indican que extrañamente la comunicación era perfecta poco antes y que ya han revisado los archivos de configuración como el listener.ora y el tnsnames.ora y que todo se ve bien pero aún así no logran establecer nuevas conexiones. Un detalle adicional es que todos estos casos tienen el común denominador de que el puerto en uso no es el usual 1521 sino algún otro. Considerando este escenario pre-determinado, síganme para ver lo simple que puede ser resolver este problema.

Conceptos previos

El background process PMON se encarga de registrar dinámicamente con el listener los servicios disponibles en una base de datos, lo cual se conoce como registro dinámico de servicios. Ahora bien, hay que tener en cuenta que por defecto las bases de datos Oracle registran sus servicios con el listener asumiendo que éste está atendiendo por el puerto 1521, si se usa un puerto distinto a éste se requiere de medidas adicionales para permitir que PMON sepa dónde registrar los servicios de la base de datos o no lo logrará hacer y caeremos en el error ORA-12514.

Solución

1. No es inusual que se configure un puerto distinto al 1521, hay varias razones para ello pero principalmente se hace como medida de seguridad adicional para prevenir ataques que aprovechan justamente que la gran mayoría deja su listener configurado con el puerto por defecto 1521, de allí que cambiarlo sea altamente recomendado.

Veamos primeramente un listener modificado (listener.ora):

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = caliope)(PORT = 15402))
    )
  )

2. Esto se debe complementar con la configuración del parámetro local_listener, para lo cual tenemos dos posibilidades, una primera en la que colocamos los datos explícitamente:

SQL> alter system set local_listener="(address=(protocol=TCP)(host=caliope)(port=15402))";

O una segunda, en que se usa una cadena de conexión que se puede resolver mediante la consulta al archivo tnsnames.ora.

SQL> alter system set local_listener=listener_bd;

El alias listener_bd debe existir localmente, como se observa a continuación (tnsnames.ora):

LISTENER_BD =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = caliope)(PORT = 15402))
  )

3. Con esto solo nos resta verificar que la conectividad está efectivamente operativa, para lo cual consideramos la siguiente cadena de conexión (tnsnames.ora):

BD =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = caliope)(PORT = 15402))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = bd)
    )
  )

Misma que probamos con SQL*Plus

[oracle@caliope ~]$ sqlplus system/oracle@bd

SQL*Plus: Release 11.1.0.7.0 - Production on Thu Apr 1 15:19:17 2010

Copyright (c) 1982, 2008, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SYSTEM@bd >

¡Todo funcionó a la perfección!

Conclusión

¿Qué les pareció? ¿No está complicado verdad?, pero les sorprendería saber cuántos no siguen estas consideraciones y luego de crear listeneres adicionales, observan que se interrumpen las nuevas conexiones luego de detener el listener que usa el puerto 1521 y se pregunta el por qué, si se supone que esas bases de datos usan otros puertos en otros listeners; bueno, ahora ya lo saben, así que: ¡a corregir se ha dicho!

¿Te pareció interesante este artículo?, ¿te quedaron algunas dudas?, ¿quieres sugerirme un tema a tratar?, pues déjame tus comentarios o envíame un email y para que NO te pierdas ningún Post, suscríbete por email ahora mismo!

11 comentarios, agrega el tuyo!

Yane dijo...

Interesante y practico, ahora voy a realizar una prueba con ello , Gracias por tu aporte :)

Anónimo dijo...

Marm:
Hola, es bastante interesante porque suelen ser errores tontos que no aprecias y que dan problemas. Pero en mi caso, tengo la configuración por defecto, el puerto correcto y me da ese error. Estoy loca, sin saber por qué!

Markis dijo...

Oye Marm, no se si ya has conseguido solucionar tu problema, muchas veces el problema es porque el puerto lo esta utilizando otro servicio, debes verificar que nadie este utiliando el puerto.

Si tienes problemas deja tu email para ayudarte!

Anónimo dijo...

Tengo un problema similar al que describes, mi aplicación se conecta por medio de un jdbc dinamico a la base de datos.

JDBC es dinamico debido a que tiene una de respaldo y entonces en cuanto falla la actual se conmuta a la otra.

Estaba trabajando perfectamente bien con esta configuracion, hasta hace algunos dias, ya verifique los puntos que comentas, pero aun sigue el problema.

Me puedes sugerir que mas podria revisar, para resolver el problema

Guido dijo...

Gracias, me salvaste!

Igualmente un detalle para los que como yo, no son expertos en ORACLE

para realizar el "alter system set local_listener="(address=(protocol=TCP)(host=caliope)(port=15402))";"

tenes que ejecutar

sqlplus / as sysdba

una vez adentro y con los servicios del oracle levantado ingrese

sql> STARTUP

ahi me levanto todo bien y luego

sql> alter system set local_listener="(address=(protocol=TCP)(host=caliope)(port=15402))";

y llego el hermoso "Sistema modificado."

Nuevamente gracias!

Fintriago dijo...

excelente solucion amigo.
Saludos desde Ecuador
Fintriago

Anónimo dijo...

hola, soy novato en oracle, y tengo este grave error, no me funciona como explicas o talves no lo ago bien, como queda un listener modificado, en q parte pongo lo anterior q explicas, porfas ayud.

Enrique Orbegozo dijo...

Hola "anónimo", comprenderás que es algo difícil dar soporte por este medio, más aun cuando no me das información alguna sobre tu instalación y lo que has hecho hasta el momento para tratar de resolver el problema.
Saludos.

El pibe dijo...

huy viejo me has salvado, excelente la explicacion sin tanta complicacion y lo necesario. Esto lo utilizo cuando actualizo la version de oracle por parche que te registra otro puerto de listener en vez del estandar.

Gracias, voy a publicar tu nota en mi blog, www.blogdelpibe.com.

Un saludo.

El pibe dijo...
Este comentario ha sido eliminado por el autor.
Daniel dijo...

Muy bien explicado, gracias aun que en mi instalación no me funciono y me surgieron algunas dudas, busque por la web y no encontré información precisa:

tengo dos escenarios:

PRIMER:
Instale oracle y me crea la BD y el listener por defecto en el puerto por defecto, luego usando las herramientas de Oracle "Configuration and Migration tools" añado una nueva base de datos, me creo un nuevo listener con el net manager apuntando a un nuevo puerto, configure el local_listener como mencionaste. pero no puedo hacer una conexión remota.

nota: en este caso instale la BD en el mismo $ORACLE_HOME asi que el archivo listener.ora tiene mas de una configuracion.

SEGUNDO:
Instale oracle por defecto al igual que el primer escenario, la diferencia es que instale otra base de datos con el mismo instalador y resulto que me pude crear un $ORACLE_HOME distinto al primero y el listener tambien se creo por defecto, lamentablemente tampoco pude conectarme remotamente a la nueva base de datos

nota: tenemos 2 bases de datos en diferentes ORACLE_HOMEs cada uno con un archivo listener.ora ambos llamados de la misma manera pero con puertos diferentes.

PREGUNTA:

Es posible tener 2 listeners running con diferente nombre y puerto, uno apuntando a una BD y la otra apuntando a una nueva BD? para ambos escenarios?


De antemano les agradezco la ayuda.
Saludos,
Daniel.