viernes, 4 de noviembre de 2011

¿Cómo reemplazar el uso de Sinónimos?


Una de las desventajas del uso de sinónimos privados es que ocupa mas espacio en el diccionario del SYS y en memoria, ya que para cada usuario de base de datos se deberá crear los sinónimos privados para que este pueda ver los objetos sin necesidad de escribir la ruta absoluta.
¿Ruta absoluta? Con esto quiero indicar que no debemos anteponer el nombre del esquema propietario seguido de un punto y el nombre del objeto, pero para entenderlo mejor veamos un ejemplo.
Vamos a crear una tabla BD_USUARIOS con el usuario SISOWN.
C:\>sqlplus sisown@orcl
Introduzca la contrase±a:
SQL> create table bd_usuarios as select * from dba_users;
Tabla creada.
SQL> select count(*)cantidad from bd_usuarios;
CANTIDAD
----------
23

Creamos al usuario PRUEBA_1 con los permisos de consulta a la tabla BD_USUARIOS.
SQL> create user prueba_1 identified by hola;
Usuario creado.
SQL> grant connect to prueba_1;
Concesi¾n terminada correctamente.
SQL> grant create synonym to prueba_1;
Concesi¾n terminada correctamente.
SQL> grant select on bd_usuarios to prueba_1;
Concesi¾n terminada correctamente.
SQL> connect prueba_1/hola
Conectado.
SQL> select count(*)cantidad from bd_usuarios;
select count(*)cantidad from bd_usuarios
*
ERROR en lÝnea 1:
ORA-00942: la tabla o vista no existe
SQL> select count(*)cantidad from sisown.bd_usuarios;
CANTIDAD
----------
23

Al conectarnos con PRUEBA_1 y realizar la consulta a la tabla BD_USUARIOS nos da error de que la tabla o vista no existe ya que a nivel de usuario PRUEBA_1 no existe la tabla, pero en la segunda consulta lo realizamos anteponiendo el nombre del usuario propietario SISOWN.BD_USUARIOS y no nos da error la consulta.

El error se presenta por que al realizar la consulta lo primero que se hace es ver si la tabla existe a nivel en el esquema PRUEBA_1 y al no encontrarlo se produce el error.
Para evitar ubicar el nombre del esquema antes del objeto en toda la programación tenemos 3 opciones:
  1. Utilizar sinónimos privados
  2. Utilizar sinónimos públicos
  3. Cambiar la variable de sesión CURRENT_SCHEMA
Utilizar sinónimos privados
Los sinónimos privados son objetos que pertenecen a cada usuario de la base y son alias que le damos a los objetos de base de datos y nos evitaría llamar a los objeto por rutas absolutas.

C:\>sqlplus prueba_1@orcl
Introduzca la contrase±a:
SQL> select count(*)cantidad from bd_usuarios;
select count(*)cantidad from bd_usuarios
*
ERROR en lÝnea 1:
ORA-00942: la tabla o vista no existe
SQL> create or replace synonym bd_usuarios for sisown.bd_usuarios;
Sin¾nimo creado.
SQL> select count(*)cantidad from bd_usuarios;
CANTIDAD
----------
23

Vemos como creando el sinónimo privado ya no se necesita de ubicar ruta absoluta (Esquema y objetos) para poder llamar a la tabla BD_USUARIOS. Esto deberá definirse para cada usuario de todos los objetos (Tablas, procedimientos, vistas, secuencias, etc) del usuario propietario 

Utilizar sinónimos públicos
Los sinónimos públicos a diferencias de los privados es que son de dominio público, es decir que solo se necesita definir una sola vez y todos para que sean visto por los demás usuarios, la ventaja de esto es que no debemos definirlo por cada usuario sino una sola vez.

C:\>sqlplus sisown@orcl
Introduzca la contrase±a:
SQL> create or replace public synonym bd_usuarios for sisown.bd_usuarios;
Sin¾nimo creado.
SQL> connect prueba_1/hola
Conectado.
SQL> select count(*)cantidad from bd_usuarios;
CANTIDAD
----------
23

Cambiar la variable de sesión CURRENT_SCHEMA
Esta manera es más eficiente que las dos anteriores, ya que no se necesita de crear objetos adicionales, solo se debe de indicar a la sesión de usuario que esquema de datos se va usar(Es decir en donde primero debe de buscar el objeto). La variable de sesión que modificamos es la CURRENT_SCHEMA la cual indica hacia que esquema se debe de buscar los objetos. Por default el CURRENT_SCHEMA es igual al nombre de la sesión de usuario.

C:\>sqlplus prueba_1@orcl
Introduzca la contrase±a:
SQL> select count(*)cantidad from bd_usuarios;
select count(*)cantidad from bd_usuarios
*
ERROR en lÝnea 1:
ORA-00942: la tabla o vista no existe
SQL> alter session set current_schema=SISOWN;
Sesi¾n modificada.
SQL> select count(*)cantidad from bd_usuarios;
CANTIDAD
----------
23

 Si me preguntaran cual es la mejor método a implementar, pues les daría el siguiente orden: Cambiar CURRENT_SCHEMA, Creación de sinónimos públicos y creación de sinónimos.

¿Por qué es mejor alterar el CURRENT_SCHEMA?
Es mejor porque no se necesita la creación de objetos en el diccionario del SYS, además de que en la memos ocupación de la Library Cache(Ya que por cada usuario no se cargaria metadata del objeto sinonimo) lo que es una ventaja por que dejamos más espacio disponible en la shared pool.

Si tenemos un ambiente de base de datos con 100 usuarios y esos usuario hacen uso de un promedio de 3,000 objetos de un esquema propietario (Tablas, vistas, procedimientos, secuencias, etc), para esto tendriamos que crear 300,000 sinonimos y considerar que cada vez que se cree un usuario el tiempo que nos tomará crear todos los sinonimos para este usuario.

Ademas otro punto en contra de los sinónimos es que cada vez que realices un cambio en los objetos del esquema propietario ya se estructural o de progrmación, los sinonimos relacionados a estos objeto se invalidan por lo que hay que recrearlos para evitar problemas.

¿Se puede hacer de manera automática el cambio del CURRENT_SCHEMA?
Si no deseas cambiar código de programación en tu sistema y deseas que esto se haga de manera automática en la base de datos lo que puede usar es un trigger de base de de datos AFTER LOGON:
CREATE OR REPLACE TRIGGER SISOWN.DB_CONTROL_SESION
AFTER LOGON
ON DATABASE
DECLARE
/***********************************************************
Desarrollado por : Víctor Endara
Objetivo : Cambiar de manera automática la el CURRENT_SCHEMA
************************************************************/
BEGIN
  if user not in ('SYS','SYSTEM','SYSAUX','SYSMAN') then
   execute immediate 'alter session set current_schema=SISOWN';
  end if;
  EXCEPTION
  WHEN OTHERS THEN
   RAISE;
END ;
/

1 comentario:

  1. El problema de cambiar de schema viene cuando usas pools de conexiones.
    Hay drivers que borran todas las variables de la conexión cuando la devuelven al pool, incluido el schema por lo que en una aplicación, cuando vuelva a pedir una conexión al pool no se ejecutará el alter y fallará.

    ResponderEliminar