problemas comunes con el rollback segment en oracle

Anuncio
PROBLEMAS COMUNES CON EL ROLLBACK SEGMENT
EN ORACLE
Hemos detectado problemas relacionados con dos características del ORACLE: integridad transaccional y
"read consistency". Ambas se "apoyan" sobre el Rollback segment, pero son diferentes y tienen una
diferencia fundamental que es el momento en el cual se "liberan" los rollback segments.
La integridad transaccional se refiere a que se garantiza el rollback en caso de "caída" de la conexión o
similar, por esto, al hacer un commit los rollback segments utilizados se liberan. Puede haber variaciones
por tener "delayed block clean out" pero básicamente es así.
El read consistency lo que significa es que si se ejecuta una consulta los datos resultantes de la misma van
a ser los datos al momento de comienzo de la consulta y nos se van a "ver" los datos modificados en el
interim. Esto se maneja con un esquema de numeración de las consultas (System Change Numbers, que
básicamente es un "timestamp"). Entonces, si un registro fue modificado el valor del mismo se obtiene
del Snapshot ("foto" antes de la modificación) y no de la tabla en si. Este Snapshot forma parte del
Rollback Segment.
Este esquema no se ve afectado por los commits, porque a pesar de que se haga un commit el Snapshot
debe ser conservado por consultas que hayan sido ejecutadas (comenzadas) antes de la actualización de
ese registro.
En conclusión, si se ejecuta un select * from tabla1, luego se ejecuta un update en la tabla1, entonces el
select "verá" el valor de las tuplas antes de la modificación (los snapshots), independientemente de si
luego del update se ejecuto o no un commit.
Errores comunes relacionados al rollback segment
1.
Problema ORA01562 - failed to extend rollback segment (id = 6) # extents (121) reached for
rollback segment RB5
Esto significa que se intenta hacer un update/insert y no hay lugar suficiente en el rollback segment (por
lugar o por máximo de "extensions") para garantizar la integridad transaccional.
Se soluciona incluyendo un COMMIT cada tanto para "liberar" los Rollback Segments y que puedan ser
re-utilizados.
Por ejemplo si se tienen los siguientes comandos:
Do while
new
endnew
enddo
Si la cantidad de inserts es tal que no alcanza el rollback segment para garantizar la integridad
transaccional, entonces aparecerá el error.
Se debe modificar el fuente del siguiente modo:
Do while
new
endnew
commit
enddo
NOTA: el commit puede ser incluido cada X cantidad de registros para no hacer uno por registro.
2.
Problema ORA01555 - Snapshot too old (rollback segment too small)
Esto significa que se va a requerir un Snapshot y el sistema no puede garantizar que el mismo exista. O
dicho en otras palabras, no se puede garantizar la "Read consistency"
Esto se da cuando se llenan los rollbacks segments y se quieren reutilizar pero no se puede porque se
deben conservar todos los rollbacks segments porque hay un select que requiere "read consistency".
Un ejemplo claro de esto:
For each // tabla 1
new //tabla 2
endnew
commit
endfor
El primer For Each significa un SELECT ... que comienza a la hora, por ejemplo, a las 14:00
Los "news" comienzan a utilizar los rollback segments. Como existe el commit después de cada new, no
tienen problemas de utilización de los rollback segments, porque el mismo (el new) no los volverá a
utilizar pues hizo el commit (si no hiciera commit daría el error ORA-01562 o similar). Llega un
momento en el cual los rollback segments se acaban (por espacio o por cantidad de "extensions").
Entonces, al hacer el próximo fetch del For each (select) no se puede garantizar que exista el Snapshot
pues se llenaron los Rollback Segments.
O sea, el commit no es una solución a este problema pues si bien "libera" los Rollback Segments para la
integridad Transaccional, no los libera realmente por el read-consistency.
Esto significa que incluir un commit después de cada insert no garantiza evitar este problema pues sigue
dependiendo del tamaño de los Rollback Segments.
El commit seria solución si se tuviera una estructura como:
Do while
new
endnew
commit
enddo
en este caso no existe select que requiera read-consistency y no se produce el problema.
Otra posible variación seria reducir la cantidad de Selects, el procedimiento quedaria algo similar a lo
siguiente:
final=0
// inicializo la variable de finalización en 0
posición = 0
// inicializo la variable en un valor que me tome el primer reg. de la tabla
Do while final = 0 // mientras no llegue al final del archivo
cntreg= 0 // inicializo la cnt. de reg. procesados en 0
For each
where clave > posición // me posicione en el primer reg. o en el siguiente
// al ultimo que procese en el SELECT (For each)
// anterior.
final = 1
// supongo que me voy a ir porque termino la tabla
new
// doy el alta
endnew
CntReg=CntReg+1
If CntReg>10000
// si procesé 10 mil reg.
clave=posicion // guardo la ultima posición procesada
final=0
// no se ha terminado la tabla
exit
// fuerzo la salida del select (For each)
endif
endfor
commit
// hago el commit de los 10 mil reg. procesados
// o de los procesados la ultima vez
enddo
En definitiva, lo que hago es reducir los selects a 10.000 registros, con eso soluciono el problema
ORA01555 y con el commit el problema ORA01562.
NOTA: evidentemente el Rollback Segment debe ser suficiente grande como para "almacenar" 10.000
registros.
Descargar