Estado del Cluster/Rac/Grid tabulado

Nos hemos mudado a bloger!
El contenido actualizado de esta entrada lo tienes en:
http://dba.pamplona.name/2013/12/estado-del-clusterracgrid-tabulado.html

Hoy vamos a ver una entrada de esas sencillas para hacernos la vida mas fácil.

Cuando ejecutamos el comando para ver el estado de un cluster, nos solemos encontrar con esto :

grid@rac1:/opt/oracle/10.2/CRS/bin$ crs_stat -t
Name Type Target State Host
------------------------------------------------------------
ora....SM1.asm application ONLINE ONLINE oradb1
ora....D1.lsnr application ONLINE ONLINE oradb1
ora.oradb1.gsd application ONLINE ONLINE oradb1
ora.oradb1.ons application ONLINE ONLINE oradb1
ora.oradb1.vip application ONLINE ONLINE oradb1
ora....SM2.asm application ONLINE ONLINE oradb2
ora....D2.lsnr application ONLINE ONLINE oradb2
ora.oradb2.gsd application ONLINE ONLINE oradb2
ora.oradb2.ons application ONLINE ONLINE oradb2
ora.oradb2.vip application ONLINE ONLINE oradb2
ora....robd.db application ONLINE ONLINE oradb1
ora....dmin.cs application OFFLINE OFFLINE
ora....bd1.srv application OFFLINE OFFLINE
ora....ckup.cs application OFFLINE OFFLINE
ora....bd2.srv application OFFLINE OFFLINE
ora....atch.cs application OFFLINE OFFLINE
ora....bd2.srv application OFFLINE OFFLINE
ora....oltp.cs application OFFLINE OFFLINE
ora....bd1.srv application OFFLINE OFFLINE
ora....bd2.srv application OFFLINE OFFLINE
ora....d1.inst application ONLINE ONLINE oradb1
ora....d2.inst application ONLINE ONLINE oradb2

Realmente no nos sirve de mucho ya que queda todo apiñado,y no nos permite saber que componente está arrancado y cual eta parado.
Navegando por internet vi en un par de webs (perdón pero no recuerdo el lugar) el siguiente scipt en ksh

!/usr/bin/ksh
#
#  $GRID_HOME debe de estar definido en el entorno 
#
RSC_KEY=$1
QSTAT=-u
AWK=/bin/awk
# Table header:echo ""
$AWK \
'BEGIN {printf "%-45s %-10s %-18s\n", "HA Resource", "Target", "State";
printf "%-45s %-10s %-18s\n", "-----------", "------", "-----";}'
# Table body:
$GRID_HOME/bin/crs_stat $QSTAT | $AWK \
'BEGIN { FS="="; state = 0; }
$1~/NAME/ && $2~/'$RSC_KEY'/ {appname = $2; state=1};
state == 0 {next;}
$1~/TARGET/ && state == 1 {apptarget = $2; state=2;}
$1~/STATE/ && state == 2 {appstate = $2; state=3;}
state == 3 {printf "%-45s %-10s %-18s\n", appname, apptarget, appstate; state=0;}'

Este script nos devuelve una salida limpia al estilo de :

grid@rac1:/opt/oracle/10.2/CRS/bin$ ./crsstat.sh
HA Resource                         Target     State
-----------                         ------     -----
ora.oradb1.ASM1.asm                ONLINE     ONLINE on oradb1
ora.oradb1.LISTENER_oradb1.lsnr    ONLINE     ONLINE on oradb1
ora.oradb1.gsd                     ONLINE     ONLINE on oradb1
ora.oradb1.ons                     ONLINE     ONLINE on oradb1
ora.oradb1.vip                     ONLINE     ONLINE on oradb1
ora.oradb2.ASM2.asm                ONLINE     ONLINE on oradb2
ora.oradb2.LISTENER_oradb2.lsnr    ONLINE     ONLINE on oradb2
ora.oradb2.gsd                     ONLINE     ONLINE on oradb2
ora.oradb2.ons                     ONLINE     ONLINE on oradb2
ora.oradb2.vip                     ONLINE     ONLINE on oradb2
ora.rac.db                         ONLINE     ONLINE on oradb1
ora.rac_admin.cs                   OFFLINE    OFFLINE
ora.rac_admin.rac1.srv             OFFLINE    OFFLINE
ora.rac_backup.cs                  OFFLINE    OFFLINE
ora.rac_backup.rac2.srv            OFFLINE    OFFLINE
ora.rac_batch.cs                   OFFLINE    OFFLINE
ora.rac_batch.rac2.srv             OFFLINE    OFFLINE
ora.rac_oltp.cs                    OFFLINE    OFFLINE
ora.rac_oltp.rac1.srv              OFFLINE    OFFLINE
ora.rac_oltp.rac2.srv              OFFLINE    OFFLINE
ora.rac.rac1.inst                   ONLINE     ONLINE on oradb1
ora.rac.rac2.inst                   ONLINE     ONLINE on oradb2

Nota posteriormente me he encontrado con que era un script documentado por Oracle en la nota 259301.1 :
CRS and 10g/11.1 Real Application Clusters (Doc ID 259301.1)

Pasar variables de entorno windows a un código PL/SQL

Nos hemos mudado a bloger!
El contenido actualizado de esta entrada lo tienes en:

    http://dba.pamplona.name/2013/12/pasar-variables-de-entorno-windows-un.html

    Hoy vamos a ver algo muy muy sencillo pero que puede generar un quebradero de cabeza cuando,acostumbrado a entornos Unix se trabaja con windows.

    Veamos como pasar parámetros por variables de entorno en unix

    consulta.sh

    #!/bin/bash
    export RUTA=/opt/oracle/logs
    export ORACLE_SID=miinstancia
    sqlplus -s user/pass @consulta.sql

    consulta.sql

    spool ${RUTA}/${INSTANCIA}.log
    select sysdate from dual;
    spool off 
    exit;

    ¿Como podemos conseguir lo mismo en un entorno windows?

    consulta.bat

    SET RUTA=d:\oracle\logs
    SET ORACLE_SID=miinstancia
    sqlplus -s user/pass @consulta.sql

    consulta.sql

    spool %RUTA%/%INSTANCIA%.log
    select sysdate from dual;
    spool off 
    exit;

    Como podemos ver, la diferencia es bastante pequeña y el funcionamiento final es el mismo, es un simple problema usar las variables de entorno propias de cada sistema operativo.

Monitorizar el alert.log desde una sql remota

El fichero de alertas de oracle alert.log es uno de los ficheros que tradicionalmente revisamos en busca de errores de la base de datos.
Hasta la versión 11g esta monitorización se hacía por medio del scripts que interactuaban con ficheros del sistema operativo, lo que nos llevaba a tener que mantener estos scripts para las distintas versiones de shells de sistema, o tener que instalar algún tipo de interprete en el sistema que nos lo gestionara de manera multiplataforma.

Una de las grandes ventajas de la 11g es que Oracle nos ha obsequiado con una tabla de base de datos que mapea esta información del alert.log dentro de la base de datos . Estamos hablando de la tabla x$dbgalertext;

Mediante la tabla x$dbgalertext podemos obtener toda la informacion que está en el alert.log, su contenido es:

SQL> desc X$DBGALERTEXT

           Name                            Null?    Type
           ------------------------------- -------- -------------------------
    1      ADDR                                     RAW(4)
    2      INDX                                     NUMBER
    3      INST_ID                                  NUMBER
    4      ORIGINATING_TIMESTAMP                    TIMESTAMP(3) WITH TIME ZONE
    5      NORMALIZED_TIMESTAMP                     TIMESTAMP(3) WITH TIME ZONE
    6      ORGANIZATION_ID                          VARCHAR2(64)
    7      COMPONENT_ID                             VARCHAR2(64)
    8      HOST_ID                                  VARCHAR2(64)
    9      HOST_ADDRESS                             VARCHAR2(16)
   10      MESSAGE_TYPE                             NUMBER
   11      MESSAGE_LEVEL                            NUMBER
   12      MESSAGE_ID                               VARCHAR2(64)
   13      MESSAGE_GROUP                            VARCHAR2(64)
   14      CLIENT_ID                                VARCHAR2(64)
   15      MODULE_ID                                VARCHAR2(64)
   16      PROCESS_ID                               VARCHAR2(32)
   17      THREAD_ID                                VARCHAR2(64)
   18      USER_ID                                  VARCHAR2(64)
   19      INSTANCE_ID                              VARCHAR2(64)
   20      DETAILED_LOCATION                        VARCHAR2(160)
   21      PROBLEM_KEY                              VARCHAR2(64)
   22      UPSTREAM_COMP_ID                         VARCHAR2(100)
   23      DOWNSTREAM_COMP_ID                       VARCHAR2(100)
   24      EXECUTION_CONTEXT_ID                     VARCHAR2(100)
   25      EXECUTION_CONTEXT_SEQUENCE               NUMBER
   26      ERROR_INSTANCE_ID                        NUMBER
   27      ERROR_INSTANCE_SEQUENCE                  NUMBER
   28      VERSION                                  NUMBER
   29      MESSAGE_TEXT                             VARCHAR2(2048)
   30      MESSAGE_ARGUMENTS                        VARCHAR2(128)
   31      SUPPLEMENTAL_ATTRIBUTES                  VARCHAR2(128)
   32      SUPPLEMENTAL_DETAILS                     VARCHAR2(128)
   33      PARTITION                                NUMBER
   34      RECORD_ID                                NUMBER

Ahora bien, ¿como accedemos a ella?

La tabla no puede ser accedida directamente desde un usuario que no sea sys, así que, lo que haremos será el crear una vista sobre esta tabla (a la que llamaremos por ejemplo ficheroalert ) y permitirle que lo vea a nuestro usuario de monitorizacion.


create view ficheroalert as select  * from sys.x$dbgalertext;
grant select on sys.ficheroalert to MONITORIZACION;

A partir de aquí, solamente tenemos que jugar con los campos descritos arriba y podremos obtener la informacion que deseemos.
En mi caso , por ejemplo, me gustaría saber si ha habido algún mensaje ORA- o ERROR en los ultimos 5 munitos.

La consulta que ejecutaré para obtenerlo es:


select to_char(ORIGINATING_TIMESTAMP, 'dd-mon-yyyy hh24:mi:ss'),
      substr(MESSAGE_TEXT, 1, 300) message_text
    from sys.ficheroalert
    where (MESSAGE_TEXT like '%ORA-%'
            or upper(MESSAGE_TEXT) like '%ERROR%')
     and 
           cast(ORIGINATING_TIMESTAMP as DATE) > sysdate - 5/1440;
            - X/1440 es la X en minutos 

Entrada en ingles en Monitoring the alert.log from a remote sql

oracleasm cuando no tienes la versión excta del kernel

Hoy vamos a ver una solucion casera y no soportada para cuando no tenemos la versión exacta del kernel y el módulo oracleasm.

El módulo oracleasm viene empaquetado (para RedHat,Centos) en un fichero .rpm y lo deja en el directorio /lib/modules/2.6.XX/kernel/drivers/addon/oracleasm/  . El problema lo tenemos cuando por algun motivo es necesario el actualizar la version del kernel y no hay un paquete específico de asmlib para este kernel.

En la mayoría de las veces, la nueva  version del kernel es un cambio menor de versión, y el módulo de la asmlib funcionará correctamente, nuestro problemas será que el sistema operativo intentará montar ese módulo para la versión del kernel que tenemos . Si tenemos la version YY  el sistema operativo lo buscará en /lib/modules/2.6.YY/kernel/drivers/addon/oracleasm/  y,  como hemos dicho antes, el módulo estará en /lib/modules/2.6.XX/kernel/drivers/addon/oracleasm/  lo que significa que en el arranque no cargará el módulo –> No ira el ASM –> No arrancará las instancias.

La solucion (como decía antes no soportada ) es simlemente asegurarnos que, vamos a tener nuestro modulo en el directorio que lo va a buscar el sistema operativo en el arranque.

Para ello miraremos al arrancar si exsiste el fichero  del módulo para  nuestro kernel  /lib/modules/2.6.YY/kernel/drivers/addon/oracleasm/oracleasm.ko , si no exsiste creamos el directorio y lo copiamos, si exsite, salimos y listo .

El script quedaría tal que:

#!/bin/bash
#
#  Script que copia el módulo de  oracleasm a directorio
#   kernel/drivers/addon/oracle de nuestro kernel actual
#
case "$1" in
start )
  ORIG_MODULE="/lib/modules/2.6.18-308.13.1.el5/kernel/drivers/addon/oracleasm/oracleasm.ko"
  MODULE_DIR=/lib/modules/`uname -r`/kernel/drivers/addon/oracle
  if [ ! -f ${MODULE_DIR} ]
  then
      mkdir -p ${MODULE_DIR}
      cp -p ${ORIG_MODULE} ${MODULE_DIR}
  fi
  depmod -a
;;
stop)
   true
;;
*)
    echo $"Usage: $0 {start|stop}"
    RETVAL=1
;;
esac

Una de las cosas que tenemos que tener en cuenta es que esto funcionará solo para versiones menores del kernel.

He de advertir de nuevo que, esta solución no es una solución soportada , con lo que su uso  podría limitar el soporte que oracle pueda darnos en caso de surgir algún problema, sin embargo puede ser una solucion muuy cómoda en máquinas de desarrollo,test o servidores en los que, la base de datos comparte equipo con servidores de aplicaciones o frontales web y la actualizacion de kernel no es una opcion sino una necesidad.