Purgando diag con adrci

Hoy vamos a ver una entrada sencillita en la que haremos un bash-script que nos limpie de manera ordenada el contenido del diag

El comando ADRCi permite la ejecución de comandos batch bien sea mediante la cláusula exec o bien contenidos en un fichero de texto separados por punto y coma.
Lo que vamos ha hacer es ejecutar para cada uno de los homes del la base de datos, asm y listener, el comando purge para cada uno de los tipos de elementos que guarda el diagnostics_dest

En nuestro caso, usaremos el modo script pero podíamos haber puesto todos los comandos en una línea separada por puntos y coma y el funcionamiento sería el mismo.

El script que vacia el diagnostics_dest para todo lo anterior a X días es:

#!/bin/bash
#
# Script que purga del ADRCLI  para  $1 DIAS
#
#
#
#
export ORAENV_ASK=NO
. oraenv  1>/dev/null
# Salida de debug
DEBUG=0

 #Comprobamos que se ha llamado de manera correcta
if  [ $# -ne 1 ]; then
echo "Uso Purgar_logs DIAS "
exit 3;
fi

# Inicializamos valores para el script
export TEMPORAL=/var/tmp/purgar_temporal_$$.log
export DIAS=$(($1*1440))

## Comenzamos la ejecucion
if [ $DEBUG -eq 1 ]; then
        echo "DEBUG: ORACLE_BASE=$ORACLE_BASE"
        echo "DEBUG: TEMPORAL= ${TEMPORAL} "
        echo "DEBUG: Dias= $2   en min $DIAS"
fi
# Comenzamos las iteraciones
adrci_homes=( $(adrci exec="show homes" | grep -e rdbms -e asm -e tnslsnr))
   for adrci_home in ${adrci_homes[@]}
   do
          #Generamos el fichero de comandos
         echo "set home ${adrci_home} ;" > ${TEMPORAL}
         echo "echo \"Purgamos en  ${adrci_home} \""  >> ${TEMPORAL}
         echo "purge -age ${DIAS} -type ALERT ;" >> ${TEMPORAL}
         echo "purge -age ${DIAS} -type TRACE ;" >> ${TEMPORAL}
         echo "purge -age ${DIAS} -type INCIDENT ;" >> ${TEMPORAL}
         echo "purge -age ${DIAS} -type HM ;" >> ${TEMPORAL}
         echo "purge -age ${DIAS} -type  utscdmp;" >> ${TEMPORAL}
         echo "purge -age ${DIAS} -type  cdump;" >> ${TEMPORAL}
         echo "exit; " >> ${TEMPORAL}

       if [ $DEBUG -eq 1 ]; then
        echo "DEBUG: "
        echo "DEBUG:  adrci SCRIPT=${TEMPORAL}"
        echo "DEBUG: EL etemporal es "
        echo "DEBUG: -inicio temporal-"
         cat ${TEMPORAL}
         echo "DEBUG: -fin temporal-"
        fi
        adrci  SCRIPT=${TEMPORAL}
         rm ${TEMPORAL}
    done #Fin del bucle

Como véis, es extremadamente sencillo, y bastante mas limpio que hacer el borrado a mano

Indices sin uso en SQLserver

Hoy vamos a ver una entrada referente a SQLserver.

Habitualmente cuando se habla de ajuste de índices todos tendemos a pensar en la creación de los mismos, sin embargo,la revisión del uso de los índices y la eliminación de los índices que no se usan es una tarea de administración muy recomendable, tanto por el aprovechamiento del espacio en disco como por la mejora que conlleva sobre la entrada salida (recordemos que cada inserción en una tabla indexada conlleva la actualización de los índices asociados).

SQLServer tiene desde la versión 2005 una tabla llamada SYS.DM_DB_INDEX_USAGE_STATS en la cual podemos hacer un seguimiento del uso de los indices de las bases de datos.

Los campos con los que nos quedaremos de esta tabla son

  • user_seeks: Número de consultas de búsqueda realizadas por el usuario.
  • user_scans: Número de consultas de recorrido realizadas por el usuario.
  • user_lookups: Número de búsquedas de marcadores realizadas por consultas de usuario.
  • user_updates: Número de consultas de actualización realizadas por el usuario.

Así pues, lo que debemos de buscar son índices sobre los que no hayamos hecho seeks,scans o lookups.
Esto lo podemos hacer con la consulta:

SELECT OBJECT_NAME(S.[OBJECT_ID]) AS [OBJECT NAME],
I.[NAME] AS [INDEX NAME],
USER_SEEKS,
USER_SCANS,
USER_LOOKUPS,
USER_UPDATES
FROM SYS.DM_DB_INDEX_USAGE_STATS AS S
INNER JOIN SYS.INDEXES AS I ON I.[OBJECT_ID] = S.[OBJECT_ID] AND I.INDEX_ID = S.INDEX_ID
WHERE OBJECTPROPERTY(S.[OBJECT_ID],’IsUserTable’) = 1
AND S.database_id = DB_ID()
AND user_seeks=0
AND user_scans=0
AND user_lookups=0
ORDER by user_updates DESC;
GO

Esta consulta nos devuelve algo similar a :

Resultado de la consulta

Donde podemos ver como hay índices que se encuentran sobre tablas muy actualizadas ( valor de user_updates muy alto) pero que no tienen uso en búsquedas, y otros que se encuentran sobre tablas que ni siquiera se actualizan.

Ahora nuestro trabajo es explorar esas tablas y ver si estos índices tienen sentido para, en caso de no tenerlo eliminarlos del sistema.

Monitorizando el alert con adrci

Hoy vamos a ver un pequeño script que puede ser muy útil para la monitorizacion.
Vamos a llamar a adrci indicándole que nos muestre los errores del alert desde la última vez que se ejecuto.
Para ello vamos a usar el comando show alert -p , marcándole como rango temporal a buscar la diferencia entre esta ejecución y a anterior.

#!/bin/bash
#
# Script que monitoriza el alert.log de una instancia desde la ultima vez que se ejecutó
# Si esta ultima ejecucion es menor de 5 minutos ejecuta los ultimos 5 minutos
#
#
# Si no guarda diene la guarda de ultima ejecucion sale con un ERROR
#
#  Asuminos timestamp'2015-02-18 00:07:49.767000 +01:00'
#

# Salida de debug
DEBUG=0

 #Comprobamos que se ha llamado de manera correcta
if  [ $# -ne 1 ]; then
echo "Uso adrci_alert  SID"
exit 3;
fi



# Inicializamos valores para el script
export ORAENV_ASK=NO
export TEMPORAL=/var/tmp/temporal_salida_alert_$$.log
export SALIDA=/var/tmp/salida_salida_alert_$$.log
export SID=$1
export GUARDA=/var/tmp/guarda_alert_${SID}.txt
DIA=`date +%Y-%m-%d`
HORA=`date +%H:%M:%S`
export AHORA="${DIA} ${HORA}.0000000 +01:00"
. oraenv  1>/dev/null



## Comenzamos la ejecucion
if [ $DEBUG -eq 1 ]; then
        echo "DEBUG: ORACLE_BASE=$ORACLE_BASE"
        echo "DEBUG: GUARDA= ${GUARDA}"
        echo "DEBUG: SALIDA= ${SALIDA} "
        echo "DEBUG: ORACLE_SID=$SID"
        echo "DEBUG: AHORA=$AHORA"
fi


# Buscamos ultima iteracion
if [ ! -f  $GUARDA ]; then
        echo "No tenemos ejecucion anterior"
        echo $AHORA > ${GUARDA}
        exit 1;
fi

#  Obtenemos el timestamp de la ultima ejecucion
TIEMPO=`cat ${GUARDA}`

# COmprobamos que han pasado mas de 5 minutos
OLD=`cat ${GUARDA}|awk '{print($1,$2)}'`
NOW="${DIA} ${HORA}.0000000"
SEGOLD=$(date -u -d "$OLD" +"%s")
SEGNOW=$(date -u -d "$NOW" +"%s")
DIFERENCIA=$((SEGNOW-SEGOLD))

# Comenzamos las iteraciones
adrci_homes=( $(adrci exec="show homes" | grep -e rdbms |grep ${SID}))
  for adrci_home in ${adrci_homes[@]}
    do
  #Generamos el fichero de comandos
   echo "SET TERMOUT OFF" > ${TEMPORAL}
   echo "SET ECHO OFF" >> ${TEMPORAL}
   echo "set home ${adrci_home} ;" >> ${TEMPORAL}
   echo "spool ${SALIDA} append " >>${TEMPORAL}
   echo "show alert -p \"message_text like '%ORA-%' and originating_timestamp >= \'${TIEMPO}\' \" -term " >>${TEMPORAL}
   echo "exit; " >> ${TEMPORAL}
     if [ $DEBUG -eq 1 ]; then
       echo "DEBUG: "
       echo "DEBUG:  adrci SCRIPT=${TEMPORAL}"
       echo "DEBUG: EL etemporal es "
       echo "DEBUG: -inicio temporal-"
       cat ${TEMPORAL}
       echo "DEBUG: -fin temporal-"
      fi
   adrci  SCRIPT=${TEMPORAL}   1>/dev/null
   tail -n+4 ${SALIDA}
   rm ${TEMPORAL}
done

#Actualizamos la guarda solamente si hace menos de 5 minutos que lo hemos ejecutado
if [ "$DIFERENCIA" -gt  299 ]; then
        echo $AHORA > ${GUARDA}
fi

## Añadir aqui la integración con monitorizacion

##Borramos la salida 
rm ${SALIDA}
#Salimos correctamente
exit 0 ;

A partir de aqui, solamente tenemos que integrar el tratamiento del fichero $SALIDA que es donde tendremos los errores del alert

Arquitectura CRS en 11gR2 II el CRSD

Vamos a seguir viendo la arquitectura del CRSD en la version 11gr2
Primero vamos a recordar la arquitectura del sistema
crs11g

CRSD

El Cluster Ready Services Daemon va a ser el responsable de gestionar los recursos de aplicación del cluster, esto es las bases de datos,y el resto de elementos y aplicaciones. Esta información la sacará el OCR (Oracle cluster registry )

Podemos dividir estos procesos que gestiona en dos grandes grupos:

CRSD oraagent

El CRSD oraagent administra (start/stop/check/clean) varios recursos como son bases de datos, instancias,servicios,diskgroups,node listeners,SCAN listeners…
Podemos tener mas de un oraagent (en la imagen tenemos uno para el grid y otro para la base de datos), esto sucede cuando hay mas de un propietario de la instalacin ( por ejemplo en grid y el de la base de datos)

CRSD orarootagent

CRSD orarootagent es el que se encarga de gestionar (start/stop/check/clean) Elementos como el GNS, las VIPs y los recursos de red.

Arquitectura CRS en 11gR2 I

En la version 11gR2 del RAC la arquitectura del Cluster ready services ha cambiado considerablemente.
En estas dos imágenes, podemos ver el arbol de procesos en la version 10g-11gr1 y la 11gR2

Procesos en la 10g y 11gR1
CRS10g

Procesos en la 10g y 11gR2
crs11g

Como podemos ver el arbol de procesos se ha dividido en dos ramas bien diferenciadas, el OAHSD que manejará los procesos de bajo nivel, y el CRSD que seguirá manejando estos procesos de alto nivel.

[table width=»650″ colwidth=»200|300|150″ colalign=»left|left|left»]
Elemento,Proceso ,Dueño
Oracle High Availability Service, ohasd ,init root
Cluster Ready Service (CRS), Cluster Ready Services, root
Cluster Synchronization Service (CSS), ocssd cssd monitor cssdagent ,grid owner
Event Manager (EVM), evmd evmlogger, grid owner
Cluster Time Synchronization Service (CTSS), octssd, root
Oracle Notification Service (ONS), ons eons, grid owner
Oracle Agent, oragent, grid owner
Oracle Root Agent, orarootagent, root
Grid Naming Service (GNS), gnsd, root
Grid Plug and Play (GPnP), gpnpd ,grid owner
Multicast domain name service (mDNS), mdnsd, grid owner
[/table]
Echemos un vistazo a estos daemons:

OAHASD

Es el primer proceso de todos, este es el que busca en el /etc/oracle/scls_scr/hostname
Además de usar este fichero (no es texto plano) también va a utilizar el directorio de /var/tmp/.oracle para conexiones named pipe
Wste demonio se arranca automáticamente desde el inittab y está respawneado, pero también puede hacerse desde

/etc/init.d/ini.oahsd run

El arranque y la parada será con

crscrl start crs 

crscrl stop crs

En caso de querer deshabilitar manualmente este arranque podemos hacerlo con

crsctl disable crs

crsctl enable crs

Vamos a verlos por ramas:

OAHSD oraagent

Es el agente que administra /start/stop los procesos :
[table width=»650″ colwidth=»100|550″ colalign=»left|left»]
Proceso , Funcionalidad
ora.asm,• El ASM deberá de star levantado para que el CSRD pueda acceder a la información contenida dentro\, esto es levantado desde aquí para que esté disponible
ora.emvd,•Es el Event Monitor Daemon y se encarga de publicar y suscribir los eventos del nodo ( como puede ser «database down».
ora.mdnsd,•Multicast Domain Name Services\, es usado en el PNP\, así como para res`pmder al DNS peticiones del Grid Naming Service Daemon (GNSD)
ora.GPNPD,• Grid Plug and Play Daemon \, otro de los nuevos del 11R2 que se usa par ala sincronizacion del GPnP profile entre los nodos.
ora.GPNPD,• Encargado del nuevo protocolo de intercomuicacion del grid Grid IPC
[/table]