lunes, 18 de mayo de 2009

Como reducir el tamaño del tablespace UNDO

El procedimiento que muestro a continuación, muestra los pasos a seguir cuando tenemos que recrear el tablespace UNDO en un ambiente RAC.

Estamos trabajando con un cluster de dos nodos que contienen dos Instancias de bases de datos.

Los tablespaces de UNDO de una de las instancias han crecido más de la cuenta y nos han llenado el disco.

NOTA:Una base de datos solo puede tener un tablespace de UNDO activo en un momento determinado.

En un entorno RAC, tenemos un tablespace de UNDO para cada instancia.

Un tablespace no se puede reducir de tamaño. Lo que voy a hacer es eliminarlo y volver a crearlo con un tamaño adecuado, añadiendo además un límite a su crecimiento. El problema que tengo ahora es que estoy tratando con un tablespace de UNDO, el cual tiene un tratamiento especial.

No se puede poner offline y menos aún borrarlo mientras tenga segmentos activos. De modo que, lo primero es crear un nuevo tablespace de undo, las instrucciones que indico a continuación las ejecuto como usuario SYS:


Paso 1.

CREATE UNDO TABLESPACE UNDO_TEMPORAL DATAFILE SIZE 100M;

Ahora en la primera instancia del cluster (el orden da igual) se indica el parámetro que indica el tablespace de undo por defecto.

En este caso, se trata de un parámetro dinámico, y por lo tanto no hace falta parar la instancia para poder modificarlo:

ALTER SYSTEM SET UNDO_TABLESPACE='UNDO_TEMPORAL' SID='DB1';

Si ahora reviso los parámetros que hacen referencia al UNDO en esta instancia, me encuentro con lo siguiente:

Paso2.

sqlplus> show parameter undo

NAME TYPE VALUE
—————— ———– ——————–
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDO_TEMPORAL

En teoría, ya puedo borrar el tablespace de undo que me estaba dando el problema.

Si se diera la condición de que todos los segmentos estuvieran en estado offline, no haría ni siquiera falta poner offline el tablespace; le podría hacer un drop sin más complicaciones. El problema viene cuando hay algún segmento que no está offline; teniendo claro que no quiero hacer rollback, ni recuperar ningún tipo de transacción, y que puedo prescindir totalmente de estos datos, lo que voy a hacer es forzar el estado offline de los segmentos que no lo estén para poder borrar el tablespace de forma limpia. ¿Cómo compruebo esto? Con la siguiente select:


Paso3.

SELECT SEGMENT_NAME,TABLESPACE_NAME,STATUS
FROM DBA_ROLLBACK_SEGS
WHERE TABLESPACE_NAME='UNDOTBS1';

Que me dará un resultado como el que sigue:
SEGMENT_NAME TABLESPACE_NAME STATUS
——————– ————————- —————-
_SYSSMU13$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU14$ UNDOTBS1 OFFLINE
_SYSSMU15$ UNDOTBS1 OFFLINE
_SYSSMU16$ UNDOTBS1 OFFLINE
_SYSSMU17$ UNDOTBS1 NEEDS RECOVERY
_SYSSMU18$ UNDOTBS1 OFFLINE
_SYSSMU19$ UNDOTBS1 OFFLINE
_SYSSMU20$ UNDOTBS1 OFFLINE

Cualquier status diferente de OFFLINE necesitará que le apliquemos el procedimiento que a continuación describo.

Paso4.

Lo siguiente es bajar la instancia; por suerte, estoy en un entorno RAC, por lo tanto no va a haber pérdida de servicio.

Como tengo que arrancar con un PFILE modificado a partir del SPFILE (con el que estoy trabajando), voy a crear un PFILE antes de bajar la instancia:


CREATE PFILE='/tmp/pfile.ora' from SPFILE;

Ahora bajo la instancia y edito el PFILE. Tengo que modificar el parámetro UNDO_MANAGEMENT al valor 'MANUAL' y añadir un parámetro oculto de ORACLE

para poder forzar el OFFLINE de los segmentos UNDO que no lo estén. Para el caso que describo, y según la anterior SELECT, yo insertaría esta línea

en mi PFILE:

*._offline_rollback_segments="_SYSSMU13$,_SYSSMU17quot;

Lo siguiente es levanter la instancia con el PFILE modificado:

STARTUP PFILE='/tmp/pfile.ora'

Si se ejecuta la anterior select, el resultado va a ser el mismo. Pero ahora ya se puede actuar sobre esos segmentos. En primer lugar:

DROP ROLLBACK SEGMENT '_SYSSMU13;

Que dará un resultado como este:

ERROR en línea 1:
ORA-02175: nombre de segmento de rollback no válido

Obviamos el error y repetimos el DROP sobre el otro segmento. Después de eso, ya se puede borrar el segmento de undo:


DROP TABLESPACE UNDOTBS1 INCLUDING CONTENTS AND DATAFILES;

Una vez borrado este tablespace, vuelvo a parar la instancia y arranco con el SPFILE (hago un startup sin ningún parámetro). En este momento,

ya puedo crear el nuevo tablespace de undo con los parámetros deseados:

CREATE UNDO TABLESPACE UNDOTBS1 DATAFILE SIZE 500M AUTOEXTEND ON NEXT 128M MAXSIZE 1G;

Igual que he hecho antes, cambio el tablespace de UNDO por defecto, substituyendo UNDO_TEMPORAL por UNDOTBS1.

ALTER SYSTEM SET UNDO_TABLESPACE='UNDOTBS1' SID=’DB1’;

Finalmente, solo queda repetir el proceso con la otra instancia. Cuando se concluya, se puede borrar el tablespace de UNDO que se ha creado para solucionar el problema.

1 comentarios:

Estuardo dijo...

Hola,

Yo tenia el error "snapshoot too old: rollback segment number 4 with name "_UNDOS4$" too small"

luego de seguir los pasos de tu articulo, el mensaje solo cambio a:

snapshoot too old: rollback segment number with name "" too small

ya no me muestra el numero de segmento ni el nombre.

no he podido solucionar esto ya llevo días en esto. Tienes alguna otra idea?
gracias
EA