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.