Category: Oracle 10g

Utilizando las métricas de Oracle para generar gráficos



Siempre existe la necesidad de mostrar información de manera gráfica, bien lo dice el dicho "Un dibujo vale más que mil palabras" , por ende , mostrar nu gráfico de comportamiento de algún componente de nuestra base de datos, se agradece mucho más que mostrar información de forma plana.

Para ello nos centraremos en la actividad de las vistas relacionadas a las métricas, disponibles desde Oracle10gr1 en adelante



La vista V$SYSMETRIC muestra la métrica de sistema capturada en un intervalo de 15 y 60 segundos , algunos datos importantes en esta vista

V$SYSMETRIC.BEGIN_TIME : Fecha de inicio del intervalo
V$SYSMETRIC.END_TIME : Fecha de término del intervalo
V$SYSMETRIC.INTSIZE_CSEC : Centésimas de segundo en el intervalo
V$SYSMETRIC.METRIC_NAME : Nombre de la métrica
V$SYSMETRIC.VALUE : Valor de la métrica
V$SYSMETRIC.METRIC_UNIT : Descripción de la unidad de medida, en otras palabras , como se calcula el valor de la métrica

La gracia principal de esto es que podemos capturar información de mucha utilidad y generar gráficos "para el jefe" , ¿cómo así? , pues bien ... analicemos un dato que es extremadamente importante y aparece en todos lugares , el Buffer Cache Hit Ratio

Con esta consulta sobre la V$SYSMETRIC podemos consultar el hit ratio del database buffer cache

SQL> r
1 select to_char(BEGIN_TIME,'dd-mm-yyyy hh24:mi:ss') "Fecha Inicio" ,
2 to_char(END_TIME,'dd-mm-yyyy hh24:mi:ss') "Fecha Termino" ,
3 INTSIZE_CSEC ,
4 GROUP_ID ,
5 METRIC_ID ,
6 METRIC_NAME ,
7 VALUE ,
8 METRIC_UNIT
9 from v$sysmetric
10* where metric_name like '%Buffer Cache Hit Ratio%'


Y podríamos recopilar información como la que sigue

Fecha Inicio Fecha Termino INTSIZE_CSEC GROUP_ID METRIC_ID METRIC_NAME VALUE METRIC_UNIT
------------------- ------------------- ------------ ---------- ---------- ------------------------- ------- ----------------------------------------
11-11-2009 20:11:15 11-11-2009 20:12:15 6000 2 2000 Buffer Cache Hit Ratio 100.00 % (LogRead - PhyRead)/LogRead
11-11-2009 20:12:45 11-11-2009 20:13:00 1500 3 2000 Buffer Cache Hit Ratio 100.00 % (LogRead - PhyRead)/LogRead


El problema principal (si se le puede llamar problema) es que sólo muestra 2 puntos y con eso, claramente no sabremos la tendencia de nuestra base de datos , por ende necesitamos más puntos, ¿de dónde obtenerlos?, pues del historial de esa vista , la V$SYSMETRIC_HISTORY

1 select to_char(BEGIN_TIME,'dd-mm-yyyy hh24:mi:ss') "Fecha Inicio" ,
2 to_char(END_TIME,'dd-mm-yyyy hh24:mi:ss') "Fecha Termino" ,
3 INTSIZE_CSEC ,
4 GROUP_ID ,
5 METRIC_ID ,
6 METRIC_NAME ,
7 VALUE ,
8 METRIC_UNIT
9 from v$sysmetric_history
10 where metric_name like '%Buffer Cache Hit Ratio%'
11* order by 1


Acá nos muestra la última hora de las métricas que necesitamos visualizar , lo cual ya se puede sentir como algo más elaborado , o sea, "les presentamos el comportamiento del Database Buffer Cache durante la última hora" , suena bien , está vista nos entrega información de la última hora con un total de registros de 74

Y si queremos tener una curva algo más prolongada, quizás, el último mes del Database Buffer Cache, pues allí debemos consultar la vista DBA_HIST_SYSMETRIC_HISTORY

La información viaja así ...... después de una hora en memoria en las vistas V$SYSMETRIC y V$SYSMETRIC_HISTORY , el proceso Background MMON descarga la información de estás vistas al diccionario de datos , esa información la encontramos en la vista DBA_HIST_SYSMETRIC_HISTORY

Si piensan un poco , lo anterior es lo que sucede cuando el MMON captura la información estadística desde la SGA , o sea, son los Snapshots del AWR , entre más Snapshots existan , la curva puede ser más amplia cuando analicemos información estadística, que interesante!!!

La forma en que pueden realizar los gráficos mediante la información proveniente de estas tablas, la pueden encontrar muy detallada, paso a paso en el siguiente artículo

B)B)B)Graficar en Excel información proveniente desde StatspackB)B)B)

Hay que extrapolar un poco , la información en este caso no viene del Statspack , proviene de las vistas de Oracle, pero para el caso, es aplicable 500%

¿Qué otra información es útil como métrica?

La verdad muchas otras, como por ejemplo

* CPU Usage Per Sec
* Disk Sort Per Sec
* Host CPU Utilization (%)
* Leaf Node Splits Per Sec
* Library Cache Hit Ratio
* Memory Sorts Ratio
* PGA Cache Hit %
* Physical Reads Per Sec
* Redo Generated Per Sec
* Soft Parse Ratio
* Etc,etc.

La información está , es llegar y graficar :yes:

Mayor descripción de la vista V$SYSMETRIC

De la vista V$SYSMETRIC_HISTORY

Y de la vista DBA_HIST_SYSMETRIC_HISTORY

Espero que les sirva


by Ligarius
20.01.10. 16:40:17. 770 words, 1048 views. Categories: Oracle 11g, Oracle 10g, Tuning / Performance, Oracle11gR2 , Leave a comment »Send a trackback »

Oracle10gr2 : Disminuyendo el LOG FILE SYNC con COMMIT NOWAIT


Para comenzar la charla , les pido disculpas por el tiempo alejado de las canchas, pero fue única y exclusivamente por la carga de trabajo que tenía en mi empresa, de hecho hoy en día me encuentro dictando dos cursos por día :

- Horario de tarde : WorkShop II Ed 3 de Oracle10g
- Horario de noche : Oracle Reports Builder 11g

Así que imagínense el tiempo que tengo, pero bueno... a lo que vinimos...



El evento de espera LOG FILE SYNC se da cuando una sesión de usuario ejecuta un final de transacción por ejemplo un COMMIT o un ROLLBACK , la información almacenada en el Log Buffer para esa transacción necesita ser envíada a disco , especificamente a los archivos de redolog, cuando está finaliza , la sesión recién comienza a generar otras actividades, en otras palabras, cuando se ejecuta un término de transacción la sesión entra en un evento de espera, que está relacionado al tiempo que demora el LGWR en escribir las entradas del log buffer (en realidad son vectores, pero es materia de otro Post) hacía los redologs, cuando eso finaliza .. la transacción se acepta como válida.


A veces , cuando la aplicación es muy transaccional , el LOG FILE SYNC , aparece como un Top 5 dentro del Statspack o dentro un AWR Rpt, cuando sucede eso, hay formas de mejorar esos tiempos de respuesta.



Observación : No se recomienda llevar a cabo estos cambios sin la visación de Oracle Support




Ejecución de commit asincrónico

Como ya vimos el proceso del commit y como se vaciaban los registros desde el Log Buffer , pasamos a señalar el como ejecutar el commit asincrónico para solucionar el evento de espera LOG FILE SYNC


El comando commit posee variaciones , las cuales se pueden apreciar en el siguiente detalle
WAIT : No se retorna el mensaje de commit exitoso hasta que las entradas del LogBuffer hayan sido escritas a los redo logs

NOWAIT : El commit puede retornar el control a la aplicación aunque aún la sentencia no este registrada a los archivos de redologs, lo cual puede resultar algo peligroso.

IMMEDIATE : El proceso LGWR escribe de forma inmediata la entrada de la transacción presente en los log buffer hacía los redo logs, en otras palabras , se fuerza un I/O

BATCH : Este modo le indica a Oracle que a pesar de haber finalizado la transacción con un commit, la bajada de los vectores desde el log buffer se produzca en el ciclo normal del log buffer , por ejemplo , cuando se llena a un tercio

Por defecto , cuando ustedes ejecutan el commit se ejecuta con WAIT IMMEDIATE , pero esto se puede modificar ejecutando la siguiente sentencia

COMMIT WRITE NOWAIT IMMEDIATE , o sea, no espera a que se escriba la información del log buffer a los redo logs, entrega el control a la aplicación y hace la bajada de la información del log buffer de forma inmediata a los redo logs

Es una opción que hay que manejar con cuidado , pues puede haber pérdida de datos , por ejemplo este comando

COMMIT WRITE NOWAIT BATCH , puede dejar mucha información en memoria , indicarles que se hizo el commit exitoso y ante una caída quedar con información inconsistente.

Todo lo anterior también se puede setear mediante el parámetro de incialización correspondiente

COMMIT_WRITE

Y analizando toda esta información , para solucionar en parte el evento de espera LOG FILE SYNC , se podría cambiar el modo del commit para los procesos batch de la siguiente forma

COMMIT WRITE NOWAIT BATCH

Espero que les haya servido

Documentación necesaria
Parámetro COMMIT_WRITE
Evento de espera LOG FILE SYNC


by Ligarius
02.12.09. 13:23:18. 632 words, 903 views. Categories: Oracle 11g, Oracle 10g, SQL / Programación, Tuning / Performance , Leave a comment »Send a trackback »

Problema de la vida real : No se puede montar un Diskgroup en una instancia ASM



Estando en un cliente, realice una "inocua" |-| , bajada de servicios de Cluster y rebooteo de máquina

Baje la base de datos

$srvctl stop database -d


ervicios completos del Clusterware

$crs_stop -all


Para posteriormente , reiniciar los nodos

#reboot


Cuando volvieron los servicios a la máquina y levanto el Clusterware, me encuentro con este panorama

[oracle@dtv-ora-02 ~]$ crs_stat -t
Name Type Target State Host

------------------------------------------------------------
ora....SM1.asm application ONLINE ONLINE dtv-ora-01
ora....01.lsnr application ONLINE ONLINE dtv-ora-01
ora....-01.gsd application ONLINE ONLINE dtv-ora-01
ora....-01.ons application ONLINE ONLINE dtv-ora-01
ora....-01.vip application ONLINE ONLINE dtv-ora-01
ora....SM2.asm application ONLINE ONLINE dtv-ora-02
ora....02.lsnr application ONLINE ONLINE dtv-ora-02
ora....-02.gsd application ONLINE ONLINE dtv-ora-02
ora....-02.ons application ONLINE ONLINE dtv-ora-02
ora....-02.vip application ONLINE ONLINE dtv-ora-02
ora.ibs.db application ONLINE OFFLINE
ora....s1.inst application ONLINE OFFLINE
ora....s2.inst application ONLINE OFFLINE

Mmmm , malo muy malo.. no levanta mi base de datos , pensé que era problema del ASM , pero este se encontraba arriba (eso creí en un instante)

Procedí a levantar la base de datos a mano, tampoco levantaba pues no estaba el Diskgroup DATA, ingrese a ASM y monte el Diskgroup y apareció este error..

SQL> alter diskgroup DATA mount;
alter diskgroup DATA mount
*
ERROR at line 1:
ORA-15032: not all alterations performed
ORA-15040: diskgroup is incomplete
ORA-15042: ASM disk "3" is missing

SQL>

:( , el tema se estaba complicando, pero siempre esta Metalink, Soporte Oracle y claro , mucha lectura, por eso he aquí la solución al inconveniente y claro las validaciones que se llevaron a cabo, que todos debiesen tener en cuenta cuando se trabaje con ASM ;)

Catálogo de validaciones

a) Verificar las particiones físicas en cada uno de los nodos, debiesen estar todas y no presentar GAPs

$more /proc/partitions

b) Si estamos usando ASMLib, obtener un listado de los discos involucrados y consultarlos contra ASMLib

Una forma automática

#for i in `cd /dev/oracleasm/disks;ls *`;
do
/etc/init.d/oracleasm querydisk $i 2>/dev/null
done

Una forma manual

$ su - root
Password:
# cd /etc/init.d/
# ./oracleasm listdisks
VOL1
VOL2
VOL3
VOL4
# ./oracleasm querydisk VOL1
Disk "VOL1" is a valid ASM disk
# ./oracleasm querydisk VOL2
Disk "VOL2" is a valid ASM disk
# ./oracleasm querydisk VOL3
Disk "VOL3" is a valid ASM disk
# ./oracleasm querydisk VOL4
Disk "VOL4" is a valid ASM disk
# ./oracleasm scandisks
Scanning the system for Oracle ASMLib disks: [ OK ]
#

c) Verificar las particiones desde ambos nodos

#fdisk -l

d) Verificar en ambos nodos como fueron configurados los Raw Devices

# cat /etc/sysconfig/rawdevices
/dev/raw/raw1 /dev/sdc1
/dev/raw/raw2 /dev/sde1
/dev/raw/raw3 /dev/sdg1
/dev/raw/raw4 /dev/sdi1
/dev/raw/raw5 /dev/sdk1
/dev/raw/raw6 /dev/sdm1
/dev/raw/raw7 /dev/sdo1
/dev/raw/raw8 /dev/sdq1
/dev/raw/raw9 /dev/sds1
[root@dtv-ora-01 etc]#

e) Validar los privilegios y owner, sobre los Raw Devices generados, debiese tener acceso total el usuario Oracle, y claro... ser dueño de ellos
En ambos nodos , se debiese visualizar algo así
In node1

# ls -ltr /dev/raw/raw*
crwxrwxrwx 1 oracle oinstall 162, 1 Sep 11 16:46 /dev/raw/raw1
crwxrwxrwx 1 oracle oinstall 162, 2 Sep 11 16:46 /dev/raw/raw2
crwxrwxrwx 1 oracle oinstall 162, 3 Sep 11 16:46 /dev/raw/raw3
crwxrwxrwx 1 oracle oinstall 162, 4 Sep 11 16:46 /dev/raw/raw4
crwxrwxrwx 1 oracle oinstall 162, 5 Sep 11 16:46 /dev/raw/raw5
crwxrwxrwx 1 oracle oinstall 162, 7 Sep 11 16:46 /dev/raw/raw7
crwxrwxrwx 1 oracle oinstall 162, 6 Sep 11 16:46 /dev/raw/raw6
crwxrwxrwx 1 oracle oinstall 162, 8 Sep 11 16:46 /dev/raw/raw8
crwxrwxrwx 1 oracle oinstall 162, 9 Sep 11 16:46 /dev/raw/raw9

No con tantos privilegios, basta un 660

f)Obtener información formateada de mis instancias ASM y sobre sus diskgroups, para ello se siguió la nota
Note.470211.1 How To Gather/Backup ASM Metadata In A Formatted Manner

Lo anterior entrega el estado de los ASM Disk del Diskgroup

Primer dato a tener en cuenta ¿Por qué aparece el disco como PROVISIONED, siendo que forma parte del DiskGroup? ¿Se perdió la cabecera del archivo?

Ya tenemos la metadata, donde el HEADER_STATUS del ASM Disk indica que esta PROVISIONED, para cercionarnos, vemos la información de la cabecera del archivo raw, para así compararlo con la Metadata.

g)Obtención de información de la cabecera del Raw devices con el utilitario kfed (Utilitario interno de Oracle)

Para versiones 10.2.0.X hacía arriba, se debe ejecutar lo siguiente :

Cambiar de directorio donde se encuentra el kfed

cd $ORACLE_HOME/rdbms/lib


Generar el ejecutable kfed

$make -f ins_rdbms.mk ikfed (Ojo!!!, se escribe ikfed)


Verificar que se haya generado el kfed

$ls -ltr $ORACLE_HOME/bin/kfed


Finalmente , procedemos a leer la cabecera del Raw Devices

$ORACLE_HOME/bin/kfed read /dev/raw/raw6


Y eso , nos proporciona una salida similar a esta

[oracle@bin]$ kfed read /dev/raw/raw6
kfbh.endian: 1 ; 0x000: 0x01
kfbh.hard: 130 ; 0x001: 0x82
kfbh.type: 1 ; 0x002: KFBTYP_DISKHEAD
kfbh.datfmt: 1 ; 0x003: 0x01
kfbh.block.blk: 0 ; 0x004: T=0 NUMB=0x0
kfbh.block.obj: 2147483651 ; 0x008: TYPE=0x8 NUMB=0x3
kfbh.check: 2004180404 ; 0x00c: 0x77755db4
kfbh.fcn.base: 0 ; 0x010: 0x00000000
kfbh.fcn.wrap: 0 ; 0x014: 0x00000000
kfbh.spare1: 0 ; 0x018: 0x00000000
kfbh.spare2: 0 ; 0x01c: 0x00000000
kfdhdb.driver.provstr: ORCLDISKVOL4 ; 0x000: length=12
kfdhdb.driver.reserved[0]: 877416278 ; 0x008: 0x344c4f56
kfdhdb.driver.reserved[1]: 0 ; 0x00c: 0x00000000
kfdhdb.driver.reserved[2]: 0 ; 0x010: 0x00000000
kfdhdb.driver.reserved[3]: 0 ; 0x014: 0x00000000
kfdhdb.driver.reserved[4]: 0 ; 0x018: 0x00000000
kfdhdb.driver.reserved[5]: 0 ; 0x01c: 0x00000000
kfdhdb.compat: 168820736 ; 0x020: 0x0a100000
kfdhdb.dsknum: 3 ; 0x024: 0x0003
kfdhdb.grptyp: 1 ; 0x026: KFDGTP_EXTERNAL
kfdhdb.hdrsts: 3 ; 0x027: KFDHDR_MEMBER
kfdhdb.dskname: DATA_0003 ; 0x028: length=9
kfdhdb.grpname: DATA ; 0x048: length=4

kfdhdb.fgname: DATA_0003 ; 0x068: length=9
kfdhdb.capname: ; 0x088: length=0
kfdhdb.crestmp.hi: 32924622 ; 0x0a8: HOUR=0xe DAYS=0x1e MNTH=0x8 YEAR=0x7d9
kfdhdb.crestmp.lo: 987539456 ; 0x0ac: USEC=0x0 MSEC=0x32a SECS=0x2d MINS=0xe
kfdhdb.mntstmp.hi: 32924626 ; 0x0b0: HOUR=0x12 DAYS=0x1e MNTH=0x8 YEAR=0x7d9
kfdhdb.mntstmp.lo: 2526926848 ; 0x0b4: USEC=0x0 MSEC=0x376 SECS=0x29 MINS=0x25
kfdhdb.secsize: 512 ; 0x0b8: 0x0200
kfdhdb.blksize: 4096 ; 0x0ba: 0x1000
kfdhdb.ausize: 1048576 ; 0x0bc: 0x00100000
kfdhdb.mfact: 113792 ; 0x0c0: 0x0001bc80
kfdhdb.dsksize: 51199 ; 0x0c4: 0x0000c7ff
kfdhdb.pmcnt: 2 ; 0x0c8: 0x00000002
kfdhdb.fstlocn: 1 ; 0x0cc: 0x00000001
kfdhdb.altlocn: 2 ; 0x0d0: 0x00000002
kfdhdb.f1b1locn: 0 ; 0x0d4: 0x00000000
kfdhdb.redomirrors[0]: 0 ; 0x0d8: 0x0000
kfdhdb.redomirrors[1]: 0 ; 0x0da: 0x0000
kfdhdb.redomirrors[2]: 0 ; 0x0dc: 0x0000
kfdhdb.redomirrors[3]: 0 ; 0x0de: 0x0000
kfdhdb.dbcompat: 168820736 ; 0x0e0: 0x0a100000
kfdhdb.grpstmp.hi: 32924622 ; 0x0e4: HOUR=0xe DAYS=0x1e MNTH=0x8 YEAR=0x7d9
kfdhdb.grpstmp.lo: 987471872 ; 0x0e8: USEC=0x0 MSEC=0x2e8 SECS=0x2d MINS=0xe
kfdhdb.ub4spare[0]: 0 ; 0x0ec: 0x00000000
kfdhdb.ub4spare[1]: 0 ; 0x0f0: 0x00000000
kfdhdb.ub4spare[2]: 0 ; 0x0f4: 0x00000000
kfdhdb.ub4spare[3]: 0 ; 0x0f8: 0x00000000
kfdhdb.ub4spare[4]: 0 ; 0x0fc: 0x00000000
kfdhdb.ub4spare[5]: 0 ; 0x100: 0x00000000
kfdhdb.ub4spare[6]: 0 ; 0x104: 0x00000000
kfdhdb.ub4spare[7]: 0 ; 0x108: 0x00000000
kfdhdb.ub4spare[8]: 0 ; 0x10c: 0x00000000
kfdhdb.ub4spare[9]: 0 ; 0x110: 0x00000000
kfdhdb.ub4spare[10]: 0 ; 0x114: 0x00000000
kfdhdb.ub4spare[11]: 0 ; 0x118: 0x00000000
kfdhdb.ub4spare[12]: 0 ; 0x11c: 0x00000000
kfdhdb.ub4spare[13]: 0 ; 0x120: 0x00000000
kfdhdb.ub4spare[14]: 0 ; 0x124: 0x00000000
kfdhdb.ub4spare[15]: 0 ; 0x128: 0x00000000
kfdhdb.ub4spare[16]: 0 ; 0x12c: 0x00000000
kfdhdb.ub4spare[17]: 0 ; 0x130: 0x00000000
kfdhdb.ub4spare[18]: 0 ; 0x134: 0x00000000
kfdhdb.ub4spare[19]: 0 ; 0x138: 0x00000000
kfdhdb.ub4spare[20]: 0 ; 0x13c: 0x00000000
kfdhdb.ub4spare[21]: 0 ; 0x140: 0x00000000
kfdhdb.ub4spare[22]: 0 ; 0x144: 0x00000000
kfdhdb.ub4spare[23]: 0 ; 0x148: 0x00000000
kfdhdb.ub4spare[24]: 0 ; 0x14c: 0x00000000
kfdhdb.ub4spare[25]: 0 ; 0x150: 0x00000000
kfdhdb.ub4spare[26]: 0 ; 0x154: 0x00000000
kfdhdb.ub4spare[27]: 0 ; 0x158: 0x00000000
kfdhdb.ub4spare[28]: 0 ; 0x15c: 0x00000000
kfdhdb.ub4spare[29]: 0 ; 0x160: 0x00000000
kfdhdb.ub4spare[30]: 0 ; 0x164: 0x00000000
kfdhdb.ub4spare[31]: 0 ; 0x168: 0x00000000
kfdhdb.ub4spare[32]: 0 ; 0x16c: 0x00000000
kfdhdb.ub4spare[33]: 0 ; 0x170: 0x00000000
kfdhdb.ub4spare[34]: 0 ; 0x174: 0x00000000
kfdhdb.ub4spare[35]: 0 ; 0x178: 0x00000000
kfdhdb.ub4spare[36]: 0 ; 0x17c: 0x00000000
kfdhdb.ub4spare[37]: 0 ; 0x180: 0x00000000
kfdhdb.ub4spare[38]: 0 ; 0x184: 0x00000000
kfdhdb.ub4spare[39]: 0 ; 0x188: 0x00000000
kfdhdb.ub4spare[40]: 0 ; 0x18c: 0x00000000
kfdhdb.ub4spare[41]: 0 ; 0x190: 0x00000000
kfdhdb.ub4spare[42]: 0 ; 0x194: 0x00000000
kfdhdb.ub4spare[43]: 0 ; 0x198: 0x00000000
kfdhdb.ub4spare[44]: 0 ; 0x19c: 0x00000000
kfdhdb.ub4spare[45]: 0 ; 0x1a0: 0x00000000
kfdhdb.ub4spare[46]: 0 ; 0x1a4: 0x00000000
kfdhdb.ub4spare[47]: 0 ; 0x1a8: 0x00000000
kfdhdb.ub4spare[48]: 0 ; 0x1ac: 0x00000000
kfdhdb.ub4spare[49]: 0 ; 0x1b0: 0x00000000
kfdhdb.ub4spare[50]: 0 ; 0x1b4: 0x00000000
kfdhdb.ub4spare[51]: 0 ; 0x1b8: 0x00000000
kfdhdb.ub4spare[52]: 0 ; 0x1bc: 0x00000000
kfdhdb.ub4spare[53]: 0 ; 0x1c0: 0x00000000
kfdhdb.ub4spare[54]: 0 ; 0x1c4: 0x00000000
kfdhdb.ub4spare[55]: 0 ; 0x1c8: 0x00000000
kfdhdb.ub4spare[56]: 0 ; 0x1cc: 0x00000000
kfdhdb.ub4spare[57]: 0 ; 0x1d0: 0x00000000
kfdhdb.acdb.aba.seq: 0 ; 0x1d4: 0x00000000
kfdhdb.acdb.aba.blk: 0 ; 0x1d8: 0x00000000
kfdhdb.acdb.ents: 0 ; 0x1dc: 0x0000
kfdhdb.acdb.ub2spare: 0 ; 0x1de: 0x0000






Problema
La base de datos no parte ya que la instancia ASM no puede montar uno de sus diskgroup, justamente el diskgroup que contiene el archivo de inicialización para la base de datos.

El problema radica en que la Metadata de ASM me indica que el disco esta como PROVISIONED, o sea, es candidato a formar parte de cualquier diskgroup , es como un disco nuevo, pero al volcar la cabecera del raw devices, nos damos cuenta que ya pertenece a un DiskGroup.

Solución
Hay que sacar la información de la cabecera del Raw Devices como texto, y este texto ingresarlo nuevamente al Raw Devices, para que recalcule la cabecera y con ello reescriba en el diccionario de datos de ASM.

Implementación
1) Generar un respaldo de la cabecera del Raw Devices que se muestra como PROVISIONED

$ dd if=/dev/raw/raw6 of=/tmp/raw6.dd bs=1M count=20


2) Hacer un vaciado de la cabecera del Raw Devices, pero en texto

$kfed read /dev/raw/raw6 text=raw6.txt


3) Tomar el archivo de texto y devolverlo al Raw Devices , parece un paso tonto y sin sentido, pero al realizarlo, se recalculan muchas cosas ;)

$kfed merge /dev/raw/raw6 text=raw6.txt


4) Y si ahora se visualiza el V$ASM_DISK.HEADER_STATUS de ese Disk ASM, aparecerá como MEMBER, lo que indica que si está reconocido como miembro de un DiskGroup

sql> select path,header_status from v$asm_disk;

¿Y ahora? , pues sólo queda levantar la instancia ASM, levantar la base de datos y quedar como REY...

Espero les sirva ....


by Ligarius
17.09.09. 08:17:02. 1702 words, 945 views. Categories: Base de datos, Oracle 10g, ASM (Automatic Storage Management) , 1 comment »Send a trackback »

Monitorear o no monitorear , he allí el problema



Antes nos decían que debiamos monitorear la tabla para que quedase registro de las DMLs en la tabla *_TAB_MODIFICATIONS, y claro, eso es real hasta Oracle10gr1 , en Oracle10gr2 cambia un poco el tema.

Recordar un poco que el monitoring de una tabla, se realizaba con el comando


ALTER TABLE nombre_tabla MONITORING;

Y se puede apreciar si está o no monitoreada con el comando

select owner , table_name , monitoring from dba_tables where table_name like '%NOMBRE_TABLA%';

Cuando el parámetro STATISTIC_LEVEL está en TYPICAL, el monitoreo de todas las tablas es por defecto, lo que implica que siempre se almacenará su información de DMLs en la tabla *_TAB_MODIFICATIONS (Esto es sólo en Oracle10gr2)

Ejemplo de la consulta :

SQL> select owner , table_name , tablespace_name , monitoring from dba_tables where table_name like 'TABLA_FULL_%';

OWNER TABLE_NAME TABLESPACE_NAME MON
------------------------------ ------------------------------ ------------------------------ ---
SYS TABLA_FULL_7 SYSTEM YES
SYS TABLA_FULL_6 SYSTEM YES
SYS TABLA_FULL_5 SYSTEM YES
SYS TABLA_FULL_4 SYSTEM YES
SYS TABLA_FULL_3 SYSTEM YES
SYS TABLA_FULL_2 SYSTEM YES
SYS TABLA_FULL_1 SYSTEM YES

Y ejemplo de consulta en la tabla que lleva registro de las DMLs en una tabla

SQL> select table_name , inserts , updates , deletes from user_tab_modifications where table_name like '%TABLA_FULL_1%'

TABLE_NAME INSERTS UPDATES DELETES
------------------------------ ---------- ---------- ----------
TABLA_FULL_1 0 0 0

Para llevar a cabo un pequeño ejemplo del registro de las DML , procedemos a borrar una cantidad de registros de una tabla

SQL>delete tabla_full_6 where rownum < 1000 ;

Ejecutamos el vaciado desde memoria de la información de DMLs sobre las tablas

exec dbms_stats.flush_database_monitoring_info;

Está última instrucción siempre registra las DMLs hacía una tabla, aunque se le haya realizado rollback, saca la información desde memoria y la lleva a tablas físicas, este comando se puede dejar de lado y esperar que SMON vacíe la información cada 15 minutos aproximadamente.

Ejemplo de salida

SQL> r
1 select table_name , inserts , updates , deletes from user_tab_modifications
2* where table_name like '%TABLA_FULL_1%'

TABLE_NAME INSERTS UPDATES DELETES
------------------------------ ---------- ---------- ----------
TABLA_FULL_1 0 0 1000

Y quizás la pregunta es válida.. ¿Sirve saber la cantidad de delete a pesar de que haya rollback? , uno podría pensar hay fragmentación , una forma de analizar esto podría ser contando el número de bloques cuando :
- No se ha realizado operación sobre la tabla
- Se ha producido un borrado
- Se ha realizado el rollback

La verdad , se haga o no commit, siempre se registran los datos sobre la tabla

Miremos el siguiente ejemplo

Info original

SQL> r
1 select table_name , inserts , updates , deletes from user_tab_modifications where table_name like '%TABLA_FULL_1%'

TABLE_NAME INSERTS UPDATES DELETES
------------------------------ ---------- ---------- ----------
TABLA_FULL_1 0 0 1000

Procedemos a eliminar registro de la tabla 1 (TABLA_FULL_1) , hacer rollback y vaciar la info desde memoria

SQL> SQL> delete tabla_full_1 where rownum < 100;

99 rows deleted.

SQL> rollback;

Rollback complete.

SQL>
SQL>
SQL> exec dbms_stats.flush_database_monitoring_info;

PL/SQL procedure successfully completed.

SQL>

Y consultamos nuevamente la tabla de modificaciones

SQL> select table_name , inserts , updates , deletes from user_tab_modifications where table_name like '%TABLA_FULL_1%'
2 ;

TABLE_NAME INSERTS UPDATES DELETES
------------------------------ ---------- ---------- ----------
TABLA_FULL_1 0 0 1099

Como podemos ver, igual marca los datos a pesar de que haya un rollback

¿Y registrará las modificaciones en la *_tab_modifications pues hay un incremento o disminución de bloques?

Podemos comprobarlo mediante la siguiente consulta

SQL> col segment_name format a40
SQL> r
1* select blocks , bytes/1024/1024 MB , owner , segment_name from dba_segments where segment_name like 'TABLA_FULL_1'

BLOCKS MB OWNER SEGMENT_NAME
---------- ---------- ------------------------------ ----------------------------------------
768 6 SYS TABLA_FULL_1

7 rows selected.

Ahora procedemos a borrar , hacer rollback y realizar la misma consulta

SQL> delete tabla_full_1;

101220 rows deleted.

SQL> SQL> rollback;

Rollback complete.

SQL>
SQL>
SQL> select blocks , bytes/1024/1024 MB , owner , segment_name from dba_segments where segment_name like 'TABLA_FULL_1';

BLOCKS MB OWNER SEGMENT_NAME
---------- ---------- ------------------------------ ----------------------------------------
768 6 SYS TABLA_FULL_1

Y obtenemos exactamente la misma información

¿Y si desactivamos el monitoring de la tabla, sigue guardando registro en la *_tab_modification?
La respuesta es si, ya que desactivar el monitoring, simplemente no se puede

SQL> select owner , table_name , tablespace_name , monitoring from dba_tables where table_name like 'TABLA_FULL_1';

OWNER TABLE_NAME TABLESPACE_NAME MON
------------------------------ ------------------------------ ------------------------------ ---
SYS TABLA_FULL_1 SYSTEM YES

1 rows selected.

SQL> alter table tabla_full_1 nomonitoring;

Table altered.

SQL> select owner , table_name , tablespace_name , monitoring from dba_tables where table_name like 'TABLA_FULL_1';

OWNER TABLE_NAME TABLESPACE_NAME MON
------------------------------ ------------------------------ ------------------------------ ---
SYS TABLA_FULL_1 SYSTEM YES

Con el parámetro STATISTICS_LEVEL en BASIC , nada de esto se generá de forma automática. Y tener muy en cuenta que Oracle toma en cuenta los datos de esta tabla para verificar que tablas están con más de un 10% de modificaciones (tablas stale) ante lo cual le toma estadísticas

Una consulta bastante simple para saber a que tablas se les debiese tomar estadísticas de acuerdo a la cantidad de DMLs ejecutadas , es la siguiente

col porcentaje format 9999D999

select u.TIMESTAMP,
t.last_analyzed,
u.table_name,
u.inserts,
u.updates,
u.deletes,
d.num_rows,
TO_CHAR(((U.inserts+u.deletes+u.updates)/decode(nvl(d.num_rows,0),0,1,d.num_rows)) * 100,'999D99') percent
from user_tables t,USER_TAB_MODIFICATIONS u,dba_tables d
where u.table_name = t.table_name
and d.table_name = t.table_name
and d.owner = 'SYS'
and (u.inserts is not null or u.updates is not null or u.deletes is not null)
and ((U.inserts+u.deletes+u.updates)/decode(nvl(d.num_rows,0),0,1,d.num_rows)) * 100 > 10
order by t.last_analyzed , ((U.inserts+u.deletes+u.updates)/decode(nvl(d.num_rows,0),0,1,d.num_rows)) * 100

Puede tener variaciones y ciertas especulaciones, pero es una orientadora...

Otro punto a tener en cuenta, es cuando se toman estadísticas, se elimina la información sobre la *_TAB_MODIFICATIONS

Espero les sea de utilidad


by Ligarius
19.08.09. 09:46:32. 1052 words, 610 views. Categories: Oracle 10g, Tuning / Performance , Leave a comment »Send a trackback »

Tuning SQL : Lo malo de usar UNION en los select :)



Hace poco acabo de terminar un curso de Tuning de SQL ,el código es el D19165GC20 , en ese curso hay muchos detalles los cuales uno maneja a diario, pero de lo cual en mi caso nunca he escrito.

He aquí un ejemplo, el porque siempre se debiese ocupar el UNION ALL , en vez del UNION , esto último debido a que el UNION provoca un ordenamiento implicito de los datos dentro de la PGA , a pesar de que como todos sabemos el UNION ALL entrega todas las filas a pesar de que estas se repitan , el UNION sólo entrega aquellas diferentes.

He aquí el caso del porque es tan caro el simple, común y pequeño UNION ;)

Para realizar los ejemplos, hemos creado 7 tablas las cuales tienen informacion desde la dba_objects, o sea, cada una de estas tablas posee como 55 mil registros, mas o menos.

Vaciamos la memoria, de todo bloque para que la prueba sea más acertiva.

alter system flush shared_pool ;
alter system flush buffer_cache ;

Primero utilizamos el simple UNION

select * from tabla_full_1
union
select * from tabla_full_2
union
select * from tabla_full_3
union
select * from tabla_full_4
union
select * from tabla_full_5
union
select * from tabla_full_6
union
select * from tabla_full_7
;

Cantidad de filas traídas en la consulta

50610 rows selected.

Y observamos el plan de ejecución

Execution Plan
----------------------------------------------------------
Plan hash value: 3784107405

--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 708K| 28M| | 8800 (86)| 00:01:46 |
| 1 | SORT UNIQUE | | 708K| 28M| 76M| 8800 (86)| 00:01:46 |
| 2 | UNION-ALL | | | | | | |
| 3 | TABLE ACCESS FULL| TABLA_FULL_1 | 101K| 4151K| | 151 (3)| 00:00:02 |
| 4 | TABLE ACCESS FULL| TABLA_FULL_2 | 101K| 4151K| | 152 (3)| 00:00:02 |
| 5 | TABLE ACCESS FULL| TABLA_FULL_3 | 101K| 4151K| | 152 (3)| 00:00:02 |
| 6 | TABLE ACCESS FULL| TABLA_FULL_4 | 101K| 4151K| | 152 (3)| 00:00:02 |
| 7 | TABLE ACCESS FULL| TABLA_FULL_5 | 101K| 4151K| | 152 (3)| 00:00:02 |
| 8 | TABLE ACCESS FULL| TABLA_FULL_6 | 101K| 4151K| | 152 (3)| 00:00:02 |
| 9 | TABLE ACCESS FULL| TABLA_FULL_7 | 101K| 4151K| | 152 (3)| 00:00:02 |
--------------------------------------------------------------------------------------------

Como lo aprecian , esta ordenando 28MB de información lo cual consume 76MB de espacio temporal (o sea , se esta utilizando disco) , lo cual produce I/O muy costoso.

Statistics
----------------------------------------------------------
1423 recursive calls
0 db block gets
4876 consistent gets
4679 physical reads
0 redo size
2262291 bytes sent via SQL*Net to client
37503 bytes received via SQL*Net from client
3375 SQL*Net roundtrips to/from client
22 sorts (memory)
0 sorts (disk)
50610 rows processed

Nuevamente borramos todo vestigio desde memoria.

alter system flush shared_pool ;
alter system flush buffer_cache ;

Y ejecutamos la misma consulta, pero esta vez con UNION ALL

select * from tabla_full_1
union all
select * from tabla_full_2
union all
select * from tabla_full_3
union all
select * from tabla_full_4
union all
select * from tabla_full_5
union all
select * from tabla_full_6
union all
select * from tabla_full_7
;

Trae efectivamente mas de 700 mil registros, los cuales debiesen ser procesados con un cursor, para así descartar los repetidos, es más barato y más rápido

708540 rows selected.

El plan de ejecución de la sentencia con UNION ALL

Execution Plan
----------------------------------------------------------
Plan hash value: 2473866688

-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 708K| 28M| 1061 (87)| 00:00:13 |
| 1 | UNION-ALL | | | | | |
| 2 | TABLE ACCESS FULL| TABLA_FULL_1 | 101K| 4151K| 151 (3)| 00:00:02 |
| 3 | TABLE ACCESS FULL| TABLA_FULL_2 | 101K| 4151K| 152 (3)| 00:00:02 |
| 4 | TABLE ACCESS FULL| TABLA_FULL_3 | 101K| 4151K| 152 (3)| 00:00:02 |
| 5 | TABLE ACCESS FULL| TABLA_FULL_4 | 101K| 4151K| 152 (3)| 00:00:02 |
| 6 | TABLE ACCESS FULL| TABLA_FULL_5 | 101K| 4151K| 152 (3)| 00:00:02 |
| 7 | TABLE ACCESS FULL| TABLA_FULL_6 | 101K| 4151K| 152 (3)| 00:00:02 |
| 8 | TABLE ACCESS FULL| TABLA_FULL_7 | 101K| 4151K| 152 (3)| 00:00:02 |
-----------------------------------------------------------------------------------

Y como se puede apreciar, no hay uso de espacio temporal , sólo se procesan los 28MB de datos.

Statistics
----------------------------------------------------------
1423 recursive calls
0 db block gets
51700 consistent gets
4679 physical reads
0 redo size
27134781 bytes sent via SQL*Net to client
519985 bytes received via SQL*Net from client
47237 SQL*Net roundtrips to/from client
21 sorts (memory)
0 sorts (disk)
708540 rows processed

Para que se tenga en cuenta al momento de realizar un programa

Espero les sirva


by Ligarius
17.08.09. 09:28:17. 626 words, 718 views. Categories: Oracle 10g, Tuning / Performance , Leave a comment »Send a trackback »

1 2 3 >>