Problemas con minusculas en el resource manager desde OEM12c

Hoy vamos a ver un caso que puede volvernos un poco locos y que su solución es terriblemente sencilla.

Cuando intentamos usar el resource manager para mapear nuestros usuarios a un determinado grupo de consumidores nos encontramos que podemos intentar hacerlo por algun elemento que tenga mayusculas y minusculas.
Supongamos queremos añadir a el grupo DESARROLLO los usuarios que se conectan con el e toad y SQL Developer. Para ello ejecutaríamos

BEGIN
dbms_resource_manager.clear_pending_area();
dbms_resource_manager.create_pending_area();
dbms_resource_manager.set_consumer_group_mapping(dbms_resource_manager.client_program,'Sqldeveloper.exe','DESARROLLO');
dbms_rsource_manager.set_consumer_group_mapping(dbms_resource_manager.client_program, 'toad.exe','DESARROLLO');
dbms_resource_manager.submit_pending_area();
END; 
commit;

Pero si seguimos la pista a las sesiones de estos dos programas, veremos como no se mapean correctamente con el grupo de consumidores que queremos.
Ejecutando la siguiente consulta podemos ver la causa:

select * from DBA_RSRC_GROUP_MAPPINGS
   where attribute = 'CLIENT_PROGRAM';
ATTRIBUTE        VALUE               CONSUMER_GROUP 
------------------------------------------------------------------
CLIENT_PROGRAM    SQLDEVELOPER.EXE   DESARROLLO 
CLIENT_PROGRAM    TOAD.EXE           DESARROLLO 

¿Que es lo que ha ocurrido?

El problema que tenemos aquí es que las funciones dbms_resource_manager nos van a pasar a mayusculas los valores que le pasemos entre comillas simples.
Si nos fijamos en los comandos que hemos introducido antes vemos que el nombre del client_program lo hemos introducido entre comilla simple

dbms_rsource_manager.set_consumer_group_mapping(dbms_resource_manager.client_program, 'toad.exe','DESARROLLO');

Si lo que buscamos tiene mayusculas y minusculas o simplemente minusculas, deberemos pasarle el parámetro como un literal,es decir, entre comillas dobles

BEGIN
dbms_resource_manager.clear_pending_area();
dbms_resource_manager.create_pending_area();
dbms_resource_manager.set_consumer_group_mapping(dbms_resource_manager.client_program,'"Sqldeveloper.exe"','DESARROLLO');
dbms_rsource_manager.set_consumer_group_mapping(dbms_resource_manager.client_program, '"toad.exe"','DESARROLLO');
dbms_resource_manager.submit_pending_area();
END; 
commit;

Con esto nos cogerá la informacion correctamente.

select * from DBA_RSRC_GROUP_MAPPINGS
   where attribute = 'CLIENT_PROGRAM';
ATTRIBUTE        VALUE               CONSUMER_GROUP 
------------------------------------------------------------------
CLIENT_PROGRAM    SQLDEVELOPER.EXE   DESARROLLO 
CLIENT_PROGRAM    TOAD.EXE           DESARROLLO 
CLIENT_PROGRAM    Sqldeveloper.exe   DESARROLLO 
CLIENT_PROGRAM    toad.exe           DESARROLLO 

La información completa como siempre en metalink

  • Resource Manager Plan Is not Applied With Mixed or Lower Case Application Name (Doc ID 471173.1)
  • 11G: Oracle Resource Manager Client_program Mapping Not Working, Converted to Capital Letters (Doc ID 1586148.1)

Introduccion a los servicios de Oracle

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

Problemas con los requerimientos del cliente 11gr2 en windows

Volvemos tras las vacaciones navideñas con una pequeña entrada de esas tremendamente simples, pero que pueden ser evitarnos una gran pérdida de tiempo.

Una de las cosas mas engorrosas de las instalaciones de Oracle es la instalación del cliente, en primer lugar, porque pocas veces nos especifican que es exactamente los componentes del cliente que necesitan, y en segundo lugar, por que, hasta estas últimas versiones la instalación ( especialmente la desinstalación) del cliente de windows era muy engorrosa.

Pues bien, el otro día en la instalación de un cliente 11gr2 en windows me encontré con un error nuevo:

error_instalacion_XP

Mi windows XP detectaba un error en los requerimientos de la instalacion del cliente (no instantclient), cuando, todos los requerimientos eran correctos.

La solución es tan sencilla como el habilitar el uso compartido de C$. Parece ser que el instalador utiliza «\\< servidor >\C$\temp» , con lo que si no está habilitado el recurso, la instalación falla.

La información completa del caso está (como siempre) en metalink, en la nota «Installation of 11gR2 on Windows Fails Checking Requirements [ID 1133495.1]»

Creando grupos de consumidores. A la caza del bloqueo II

Hasta el momento, en la entrada   A la caza del bloqueo I   teníamos  un  plan de recursos llamado NO_LOCKS que mataba aquellos procesos que estaban mas de 5 segundos bloqueando otra consulta. Este plan de consumidores no era muy util , ya que podía provocar estragos matando indiscriminadamente cualquier bloqueo de mas de 5 segundos, con lo que hoy daremos un paso mas para hacer de ese plan de recursos algo mas útil.

En esta entrada vamos a crear un grupo de consumidores, este grupo de consumidores nos permitirá afinar el perfil de los usuarios sobre los que queremos aplicar nuestro pal de recursos.

El grupo de consumidores lo vamos a llamar USER_NO_LOCK_ALLOW y lo crearemos de la siguiente manera:

BEGIN
 dbms_resource_manager.clear_pending_area();
 dbms_resource_manager.create_pending_area();
 dbms_resource_manager.create_consumer_group(
consumer_group =>'USER_NO_LOCK_ALLOW','Grupo de consumidores alos que no permitiremos bloqueos '
);
 dbms_resource_manager.submit_pending_area();
END;

 

Una vez tenemos nuestro grupo de consumidores creado, es el momento de decidir que usuarios queremos tener dentro de el y cuales no. Oracle 11g nos da muchas opciones para seleccionar este grupo de usuarios, algunas de ellas son:

Por esquema

Si quisieramos añadir a los usuarios del esquema «esquema1» a este grupo de consumidores usariamos el parámetro dbms_resource_manager.oracle_user  del paquete dbms_resource_manager

BEGIN
dbms_resource_manager.clear_pending_area();
dbms_resource_manager.create_pending_area();
dbms_resource_manager.set_consumer_group_mapping(
dbms_resource_manager.oracle_user,'esquema1','USER_NO_LOCK_ALLOW'
);
dbms_resource_manager.submit_pending_area();
 END;

Por maquina cliente

Supongamos que queramos aplicar incluir en nuestro grupo de consumidores solamente las sesiones que se ejecutan desde el servidor cliente «WORKGROUP\client1», para ello  usaríamos dbms_resource_manager.client_machine

BEGIN
dbms_resource_manager.clear_pending_area();
dbms_resource_manager.create_pending_area();
dbms_resource_manager.set_consumer_group_mapping(
dbms_resource_manager.client_machine,'WORKGROUP\MAQUINA1','USER_NO_LOCK_ALLOW'
);
dbms_resource_manager.submit_pending_area();
END;

Por programa

Para separar por programa usaremos la llamada dbms_resource_manager.client_program

BEGIN
dbms_resource_manager.clear_pending_area();
dbms_resource_manager.create_pending_area();
dbms_resource_manager.set_consumer_group_mapping(
dbms_resource_manager.client_program,'PROGRAMA1','USER_NO_LOCK_ALLOW'
);
dbms_resource_manager.submit_pending_area();
END;

Como podeis ver, las posibilidades son muy grandes, en esta entrada nos hemos centrado en capturar sesiones por parámetros de login, pero la funcion dbms_resource_manager.set_consumer_group_mapping permite también seleccionar usuarios por atributos de runtime-.

La lista de las opciones la podeis encontrar en la documentación del paquete
dbms_resource_manager.set_consumer_group_mapping, pero a groso modo se puede resumir en:
Login Attributes

  • oracle_user
  • service_name
  • client_os_user
  • client_program
  • client_machine

 Runtime Attributes

  • module_name
  • module_name_action
  • service_module
  • service_module_action

Ahora solamente nos quedará el incluir este grupo de consumidores en nuestro plan de recursos, indicándole que son los consumidores de este grupo a los que no se les debe permitir el bloquear al resto de los usuarios . Pero esto será en otra entrada.