Uno de los elementos mas potentes que introdujo Oracle en la versión 10g fué el uso de servicios.
Los servicios de Oracle no son otra cosa que una abstracción lógica de una instancia de base de datos. Aunque los servicios tienen mas sentido en entorno RAC, hoy vamos a ver como se configuran y para que pueden servir en un entorno de «single instance».
Supongamos tenemos una base de datos produccion en la que tenemos consolidados 4 entornos distintos ( Webfotos,Cargas,Contabilidad y Desarrollo ) que acceden a nuestra instancia con el mismo esquema,y desde servidores de aplicaciones que comparten máquina entre ellos, en el momento en que la base de datos tiene problemas nos es muy difícil el saber quien es quien.
Si pudiésemos discriminar las conexiones por una agrupación lógica, sería mas fácil el verlo, y , mas aún, si el EMC fuese capaz de separar las gráficas y estadísticas por esa agrupación.
Pues esto es exactamente lo que nos proporcionan los servicios Oracle.
En nuestro caso ficticio, vamos a crear los distintos servicios:
- Webfotos
- Cargas
- Contabilidad
- Desarrollo
De esta forma, cada conexión de estos 4 entornos usara un service_name distinto en su TNS_NAMES de cliente, y , la base de datos podrá identificar ( y limitar) a cada uno de ellos de manera separada.
Lo primero que tendremos que hacer es crear los servicios. Para esto tenemos dos maneras, o bien desde el srvctl ( en caso de RAC,Grid control u Oracle restart), o mediante el paquete DBMS_SERVICES , como nuestro caso es el de una «single instance», no nos va a quedar mas remedio que usar este paquete.
Mediante la función CREATE_SERVICE crearemos los servicios de la manera:
exec dbms_service.CREATE_SERVICE(SERVICE_NAME=>'webfotos', NETWORK_NAME=>'webfotos')
exec dbms_service.CREATE_SERVICE(SERVICE_NAME=>'cargas', NETWORK_NAME=>'cargas')
exec dbms_service.CREATE_SERVICE(SERVICE_NAME=>'contabilidad', NETWORK_NAME=>'contabilidad')
exec dbms_service.CREATE_SERVICE(SERVICE_NAME=>'desarrollo', NETWORK_NAME=>'desarrollo')
Una vez creados los servicios, los arrancaremos con la función
exec dbms_service.START_SERVICE('webfotos')
exec dbms_service.START_SERVICE('cargas')
exec dbms_service.START_SERVICE('contabilidad')
exec dbms_service.START_SERVICE('desarrollo')
Para comprobar si la creación de nuestros servicios ha funcionado, podemos chequear el parámetro service_names
SQL> select value from v$parameter where NAME='service_names';
VALUE
---------------------------
produccion,webfotos,cargas,contabilidad,desarrollo
O bien el listener con lsnrctl services
[oracle@blog] [$lsnrctl services
LSNRCTL for Linux: Version 11.2.0.2.0 - Production on 17-MAY-2013 13:31:06
Copyright (c) 1991, 2011, Oracle. All rights reserved.
Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521))
Services Summary...
Service "PLSExtProc" has 1 instance(s).
Instance "PLSExtProc", status UNKNOWN, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0
LOCAL SERVER
Service "produccion" has 1 instance(s).
Instance "XE", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:34 refused:0 state:ready
LOCAL SERVER
Service "webfotos" has 1 instance(s).
Instance "XE", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:34 refused:0 state:ready
LOCAL SERVER
Service "contabilidad" has 1 instance(s).
Instance "XE", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:34 refused:0 state:ready
LOCAL SERVER
Service "desarrollo" has 1 instance(s).
Instance "XE", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:34 refused:0 state:ready
LOCAL SERVER
Service "cargas" has 1 instance(s).
Instance "XE", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:34 refused:0 state:ready
LOCAL SERVER
The command completed successfully
Ahora, solamente tendremos que modificar los respectivos TNSNAMES de los distntos entornos para que se conecten mediante SERVICE_NAME y no mediante SID y tendremos identificados cada una de la sesiones de oracle con el servicio.
¿que beneficios nos aporta todo esto?
- Trazabilidad: Nos va a ser sencillísimo encontrar quien es el que esta haciendo algo ya que en un primer vistazo encontraremos al culpable «logico» del problema, una vez tenemos el origen del problema es mas sencillo abordarlo.
- Accounting: Vamos a poder ser capaces de ver los consumos de cada aplicacion/grupo lógico en la base de datos, lo que nos puede ser muy bueno a la hora de derivar costes o limitar recursos
- control de accesos: Si en un momento específico queremos asegurarnos de que un elemento lógico no acceda a la aplicacion, podemos detener el servicio y el resto funcionaría correctamente.Esto puede ser muy útil por ejemplo, para evitar cargas en horario diurno, o para controlar los equipos de desarrollo
Hasta ahora lo hemos visto todo muy fácil, pero .. ¿que ocurre cuando reinicias la base de datos?.
Para que la instancia levante los servicios al arrancar deberán de estar en el init.ora con la sintaxsis:
service_names='produccion','webfotos','cargas','desarrollo'
Si no es así , cuando se levante nuestra base de datos no se levantan los servicios, y esto hace que no funcione nada de lo que apunta a ellos.
La solución como os decía la principio es hacerlo desde el srvctl, pero …
¿como lo hacemos si no tenemos RAC,Grid u Oracle restart?
La respuesta es brutalmente sencilla.
[oracle@blog] [$sqlplus "/as sysdba"
SQL*Plus: Release 11.2.0.2.0 Production on Vie May 17 13:09:11 2013
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
SQL> alter system set service_names='produccion,webfotos,cargas,contabilidad,desarrollo';
System altered.
Tan sencillo como acabáis de ver, simplemente hemos de conectarnos desde el sqlplus y hacer un ALTER SYSTEM para el parámetro service_names poniendo nuestros servicios separados por comas.
Como siempre, para mas información, tenemos la documentación de Oracle del paqueteDBMS_SERVICES