Archive for the White Papers Category
LOGGING o NOLOGGING, he ahi el dilema - Parte I
4. July 2008 by admin.
Introducción
La pregunta medular sobre NOLOGGING que escucho todo el tiempo es: ¿Crear una tabla con la opción NOLOGGING significa que “jamás habrá generación de redo”, o solo la operación inicial de creación no tiene generación de redo. Otras interrogantes como: ¿Que sentencias DML generan redo? ¿Cómo y cuando se puede emplear la opción NOLOGGING?
La generación de redo es una parte vital del mecanismo de recuperación de Oracle. Sin él, una instancia no podría recuperarse en caso de caída y tampoco podría iniciar en un estado consistente. La generación excesiva de redo, es el resultado del trabajo excesivo en la base de datos.
Este documento aborda el tema de la reducción en la generación de redo, utilizando las opciones LOGGING y NOLOGGING, las diferencias entre ellas, sus mecanismos, como reducirla y cuando usarlas.
Adicionalmente, encontrará ejemplos y tips sobre el uso de cada una de ellas.
Los beneficios principales de la opción NOLOGGING sugeridos en la Guía de Administración de Base de Datos Oracle®, son:
- Ahorro de espacio en los archivos de redo log
- El tiempo que toma crear la tabla o índice disminuye
- Mejora el desempeño en la creación en paralelo de tablas grandes
“Una regla importante respecto los datos, es nunca colocarte a ti mismo en una situación no recuperable. La importancia de este lineamiento no puede tener más énfasis, sin embargo no significa que jamás puedas utilizar alternativas que ahorren tiempo o mejoren el desempeño”.
¿Que es el Redo?
Sumariemos brevemente el proceso de redo. Cuando los bloques en Oracle son modificados, incluyendo los bloques de undo, Oracle registra los cambios en forma de vectores de cambio, los cuales son conocidos como entradas de redo o registros de redo. Las modificaciones son escritas por el proceso de servidor al buffer de redo log en la SGA. Posteriormente el buffer de redo log es vaciado a los archivos en-línea de redo log, casi en tiempo real por el proceso de escritura de logs (LGWR). (Ver la figura 1)

Los redo logs son escritos por el LGWR cuando:
- Cuando un usuario envía un commit.
- Cuando el Buffer de Logs esta a 1/3 de su capacidad.
- Cuando la cantidad de entradas de redo es 1MB.
- Cada tres segundos
- Cuando sucede en la base de datos un punto de control (checkpoint). Las entradas de redo son escritas antes del checkpoint para asegurar recuperabilidad.
“Si el buffer de logs es muy reducido, entonces observaremos esperas por espacio en buffer de logs (buffer log space waits) durante la generación de redo. Es posible que el proceso LGWR no comience a escribir redo hasta alcanzar el umbral definido por _log_io_size (el valor por defecto es 1/3 del buffer de logs o 1M, lo que sea menor) ha sido excedido, y el remanente del buffer de logs pueda ser llenado antes de que el LGWR pueda completar la escritura y liberar espacio en el buffer de logs.
En el caso ideal, el buffer de logs debería ser lo suficientemente grande para hacer frente a todas las ráfagas de generación de redo, sin que se observen esperas por espacio del buffer de logs.
Comúnmente, las ráfagas mas severas de generación de redo ocurren inmediatamente después de un cambio de log, cuando la generación de redo ha sido deshabilitada por un tiempo, y existe una lista de espera de demanda por espacio en el buffer de logs” por Steve Adams.
Los archivos de redo log registran cambios a la base de datos como resultado de transacciones (Una transacción es una unidad lógica de trabajo, consistente de una o mas sentencias SQL ejecutadas por un usuario) o acciones internas del servidor Oracle. Los archivos de redo log protegen a la base de datos de la perdida de integridad en casos de fallos causados por perdidas de suministro eléctrico, errores en discos duros y así algunas otras causas. Los archivos de redo log deben ser multiplexados para asegurar que la información almacenada en ellos no se pierda en caso de un fallo en disco. Consiste en grupos de archivos de redo log y cada grupo esta integrado por un archivo de redo log y sus copias multiplexadas. Se dice que cada copia idéntica es miembro de un grupo, y cada grupo es identificado por un número. El proceso de escritura en logs (LGWR) escribe los registros de redo del buffer de redo log a todos los miembros del grupo actual de redo logs, hasta que el archivo se llena o se solicita una operación de cambio de archivo de log. Entonces, cambia el grupo activo y comienza a escribir en los archivos del siguiente grupo. Los grupos de redo log son usados de una forma circular (ver la figura 2).

Recomendación de Mejor Práctica:
Oracle recomienda que los grupos de archivos de redo logs posean al menos dos archivos por grupo, con los archivos distribuidos en discos o controladoras separadas para que de esta forma en caso fallos en el hardware no se destruya el grupo completo.
La perdida de un grupo entero de redo logs es una de las posibles fallas de medios mas serias ya que puede resultar en perdida de datos. La perdida de uno de los miembros de un grupo de redo logs, considerando un grupo con múltiples miembros, es trivial y no afecta la operación de la base de datos más allá de provocar la publicación de un mensaje de alerta en el alert log.
Hay que recordar que los redo logs influencian fuertemente el desempeño de una base de datos, ya que un commit no puede darse por realizado hasta que la información de la transacción ha sido escrita a los redo logs. Los archivos de redo log se deberán ubicar en los discos mas rápidos disponibles, atendidos por las controladoras mas rápidas. Si es posible, no compartir con ningún otro archivo de la base de datos los discos destinados a los archivos de redo log. Esto es porque solo un grupo es accesado para escritura en un momento dado; no hay implicaciones en tener miembros de distintos grupos en el mismo disco.
Para evitar la perdida de información que podría ser requerida al recuperar la base de datos a un punto especifico, Oracle posee un proceso de archivado que trabaja en segundo plano (ARCn), el cual archiva los redo logs cuando estos se llenan. Sin embargo, es importante notar que no todas las bases de datos Oracle tienen habilitado el proceso de archivado. Una instancia con el archivado habilitado, se dice que opera en modo ARCHIVELOG y una instancia con el archivado desactivado se dice que opera en modo NOARCHIVELOG.
Para determinar en que modo esta o si el archivado esta siendo usado en una instancia tenemos las siguientes alternativas: se puede verificar el valor del parámetro LOG_ARCHIVE_START que se encuentra en el archivo de parámetros de inicio (pfile o spfile - este parametro se derogo a partir de la versión 10g), ejecutar un query SQL a la vista v$database (”ARCHIVELOG” indica que el archivado esta activado, y “NOARCHIVELOG” indica que el archivado esta deshabilitado) o ejecutando el comando ARCHIVE LOG LIST.
SQL> Select log_mode from v$database;
LOG_MODE
——————-
ARCHIVELOG
SQL> archive log list
Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 8
Next log sequence to archive 10
Current log sequence 10
Estén pendientes de la siguiente parte, donde hablare sobre Generación de Redo y Recuperabilidad: como, cuando y porqué.
Muchos saludos,
Francisco Munoz Alvarez
Posted in White Papers, Tutoriales | Print | 1 Comment »
Acelerando Imports en 9i
7. May 2008 by fmunoz.
Aqui van algunos tips para ayudarte con la performance de un import en 9i.
1- Analyze solo despues de la carga (Analyze=n)
2 -Tener el export a ser importado en un disco separado de los de datos de la BD.
3- Usar commit=n
4- Utilizar un solo segmento de rollback grande y poner los demas offline durante import
5- Utilizar indexes=n y recrearlos despues de terminado el import
6- Utilizar un buffer grande para el import. ejemplo:
(opcion del import - tiempo seg -Reduccion %)
commit=y - 120 - 0
commit=y,buffer=64000 - 100 - 17%
commit=n,buffer=30720 - 72 - 40%
commit=n,buffer=64000 - 67 - 44%
7- Pre-crear tablas anticipadamente con scripts y setear ignore=y
8- Setear db_cache_size y log_buffer para un tamano mayor
9- Parar archive, (ALTER DATABASE NOARCHIVELOG;)
Despues de terminada la carga, no olvidarse de crear los indices y generar estadisticas nuevas.
Espero haberte podido ayudar con estos tips.
Saludos,
Francisco Munoz Alvarez
Posted in White Papers | Print | 1 Comment »
Tuning Grupos de Redologs
6. May 2008 by fmunoz.
Estimados,
En mi carrera, varias veces me toco ver situacion y discusiones sobre cuando y como crear nuevos grupos de Redologs en una BD Oracle.
Como ejemplo sitare una situacion que ocurrio en 2 grandes proyectos de Chile (No citare nombres para no causar problemas con algunos colegas). Mi idea de recurir a este tema no es causar discusiones y si plantear mi vision y solucion para problemas de este tipo.
Cuando se descubre un gran volumen de contecion (Wait) en redologs, en las mayoria de las veces al ver el numero de log switches se descubre que hay un gran numero de cambio de redologs por hora o en algunos casos en pequenas ventanas de tiempo.
Ejemplo:
En la BD en question ocurrian mas de 110 log switches por hora y en algunas situaciones, llegaba a casi 600.
Esta BD tenia 10 grupos de redo con dos miembros de 10 MB cada uno. Una BD de 800 GB de tamano y muy transaccional.
Debido a esto, esta BD se pisaba la cola muchas veces durante el dia causando seria contencion en ese sentido. Ese fue el motivo de mi discucion con ciertos Gurus de Oracle en Chile. La solucion de ellos era crear mas grupos de redo de 10MB, por ejemplo de 10 a 50 grupos para disminuir las veces que se pisaba la cola el log switch. Esto en mi opinion no solucionaba el problema ya que el numero de log switches por hora continuaria igual que antes. Es como por ejemplo, estar en un bote que se esta hundiendo, y para evitar esto utilizas una cuchara de sopa para sacar el agua. Por mas que te esfuerces el agua que entra es mayor al que sale. Puedes hacerlo mas rapido y solo lograras hundirte y cansarte como loco. Pero si en vez de una cuachara usaras un balde de 5 litros, podrias sacar el agua mas rapido de lo que entra y evitar que se hunda, caso sea necesario, utilizarias un balde mayor caso el monto de agua que entra es mas grande. Lo mismo se aplica en este sentido. Por eso, yo discutia que habia que aumentar el tamano de los miembros de cada grupo para controlar esta situacion. Es correcto que aumentar el tamano de los miembros de los grupos de Redolog aumentara el tamano de cada archive log, y consequentemente demorara mas el tiempo de recuperacion en caso de falla ya que la cantidad de transacciones a ser aplicada por cada archive sera mayor. Pero que es mejor?
En esta situacion se generan mas de 1000 archives de 10MB cada uno diariamente, sera mejor aplicar 1000 archives en caso de ser necesaria una recuperacion de la BD por falla fisica o logica 24 hrs despues del ultimo respaldo o aplicar 100 archives de 100MB? o 10 de 1GB? Aumentar el tamano de los miembros de los grupos de Redologs ayuda a evitar que se llenen muy rapido y que causen contencion a nivel de I/O y del LGWR y ARC.
Para saber el numero de log switches en su BD puede ejecutar el siguiente script:
spool logs.log
set echo on
set linesize 150
set pagesize 500
column day format a16 heading ‘Dia’
column d_0 format a3 heading ‘00′
column d_1 format a3 heading ‘01′
column d_2 format a3 heading ‘02′
column d_3 format a3 heading ‘03′
column d_4 format a3 heading ‘04′
column d_5 format a3 heading ‘05′
column d_6 format a3 heading ‘06′
column d_7 format a3 heading ‘07′
column d_8 format a3 heading ‘08′
column d_9 format a3 heading ‘09′
column d_10 format a3 heading ‘10′
column d_11 format a3 heading ‘11′
column d_12 format a3 heading ‘12′
column d_13 format a3 heading ‘13′
column d_14 format a3 heading ‘14′
column d_15 format a3 heading ‘15′
column d_16 format a3 heading ‘16′
column d_17 format a3 heading ‘17′
column d_18 format a3 heading ‘18′
column d_19 format a3 heading ‘19′
column d_20 format a3 heading ‘20′
column d_21 format a3 heading ‘21′
column d_22 format a3 heading ‘22′
column d_23 format a3 heading ‘23′
column Total format 9999
column status format a8
column member format a40
column archived heading ‘Archived’ format a8
column bytes heading ‘Bytes|(MB)’ format 9999
Ttitle ‘Log Info’ skip 2
select l.group#,f.member,l.archived,l.bytes/1078576 bytes,l.status,f.type
from v$log l, v$logfile f
where l.group# = f.group#
/
Ttitle off
prompt =========================================================================================================================
Ttitle ‘Log Switch on hour basis’ skip 2
select to_char(FIRST_TIME,’DY, DD-MON-YYYY’) dia,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’00′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’00′,1,0))) d_0,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’01′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’01′,1,0))) d_1,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’02′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’02′,1,0))) d_2,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’03′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’03′,1,0))) d_3,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’04′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’04′,1,0))) d_4,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’05′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’05′,1,0))) d_5,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’06′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’06′,1,0))) d_6,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’07′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’07′,1,0))) d_7,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’08′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’08′,1,0))) d_5,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’09′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’09′,1,0))) d_9,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’10′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’10′,1,0))) d_10,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’11′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’11′,1,0))) d_11,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’12′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’12′,1,0))) d_12,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’13′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’13′,1,0))) d_13,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’14′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’14′,1,0))) d_14,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’15′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’15′,1,0))) d_15,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’16′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’16′,1,0))) d_16,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’17′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’17′,1,0))) d_17,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’18′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’18′,1,0))) d_18,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’19′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’19′,1,0))) d_19,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’20′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’20′,1,0))) d_20,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’21′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’21′,1,0))) d_21,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’22′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’22′,1,0))) d_22,
decode(sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’23′,1,0)),0,’-',sum(decode(substr(to_char(FIRST_TIME,’HH24′),1,2),’23′,1,0))) d_23,
count(trunc(FIRST_TIME)) Total
from v$log_history
group by to_char(FIRST_TIME,’DY, DD-MON-YYYY’)
order by to_date(substr(to_char(FIRST_TIME,’DY, DD-MON-YYYY’),5,15) )
/
Ttitle off
prompt
spool off
Espero que esta nota ayude a algunos de uds a detectar este tipo de situaciones, es muy comun encontrar esto en muchas Bases de Datos. Es increible lo que ayuda cuando se detecta y se soluciona este problema.
Para finalizar acuerdense que cada vez que ocurre un log switch, ocurre un checkpoint o sea imaginense que si esta ocurriendo un log switch 100 veces en una hora, 100 veces el oracle limpio el buffer a disco, 100 veces actualizo los header (encabezados) de todos los archivos de la BD ,100 veces genero archives y mucho mas cosas que ocurren por debajo a nivel de procesos, consultas,etc. En estos casos dejamos el pobre DBWR que es el encargado de hacer esto con la lengua afuera y empiezan a ocurrir los “incomplete checkpoints” en el alert.log. Ya pueden imaginarse la cantidad de I/O generada tambien.
Espero haberles ayudado a entender este importante proceso de tuning de una BD.
Muchos Saludos,
Francisco Munoz Alvarez
Posted in White Papers | Print | No Comments »