miércoles, 19 de enero de 2011

Que es un registro tipo Undo

Aqui de nuevo en Oracle en Español, tratando de demistificar a la base de datos para poder entenderla, esta entrada esta un poco larga, ya que voy a tratar de dar una pequeña explicacion de lo que son los registros e información tipo Undo y todo lo que lo rodea.

Primero que nada, debemos conocer lo que es una transaccion.

Que es una Transaccion?
Una transacción es una unidad lógica y atómica de trabajo que contiene una o más sentencias de SQL. Una transaccion agrupa operaciones SQL, de forma que, o a todas las operaciones se le hace un commit, lo que significa que se aplican a la base de datos, o a todas se hace un rollback, lo que significa que se deshacen de la base de datos. Una transaccion debe de tener las propiedades de ACID

Que es un registro Undo?
Basicamente es informacion que es utilizada por Oracle para hacer un rollback (deshacer), a los cambios que hemos hecho a nuestros datos en una transaccion y principalmente tiene los siguientes tres usos:
  • Deshacer los datos en nuestra transaccion cuando ejecutamos el comando ROLLBACK
    Cuando ejecutamos un rollback,los registros de Undo son usados para deshacer los cambios en la Base de Datos a nuestra transaccion que no ha efectuado un commit.
  • Poder tener consistencia de lectura de datos
    Oracle utiliza los registros de tipo Undo para mantener una imagen consistente de los datos, mientras son modificados por otro usuario.
  • Recuperar la Base de Datos
    Los registros de tipo Undo son usados en la recuperacion de la Base de Datos, para deshacer cualquier cambio en nuestros datos a los que no se haya efectuado commit y se encuentre en los datafiles.
Este registro es manejado en un tablespace especial de tipo undo, y puedes ver que tablespace es de tipo undo en la vista dba_tablespaces
TESTDB >select tablespace_name 
from
 dba_tablespaces where contents='UNDO';
TABLESPACE_NAME
------------------------------
UNDOTBS


En este tablespace se van a almacenar unicamente segmentos de tipo undo, que a su vez este segmento esta compuesto de minimo dos undo extents,los segmentos de tipo undo son escritos en ellos de forma circular.

En este tipo de tablespace no podemos almacenar una tabla o un indice, el mismo manejador de base de datos no lo permite. Tambien hay que saber que la base de datos nos permite tener mas de un tablespace de tipo undo pero solamente uno puede estar activo a la vez.

Existe dos tipos de manejo de los registros de undo, ya sea de tipo Manual o Automatico, que el default en 11g es Automatico.En el modo Automatico, los registros de undo son manejados en lo que se conoce como segmentos de undo, en el modo manual, los registros de undo se manejan en segmentos de rollback y no se utiliza el tablespace de tipo undo.

La informacion de tipo undo se divide en tres:
  • Informacion Undo Uncommited o Active (Sin Cometer)
    Da soporte a una transaccion en ejecución, y es requerida si un usuario quiere efectuar un rollback o si la transaccion falla. Este tipo de información nunca es sobreescrita
  • Informacion Undo Commited o Unexpired (Cometida)
    Esta información ya no es requerida por la transacción, pero es necesaria para cumplir con el intervalo de tiempo definida en el UNDO_RETENTION (veremo mas abajo la definicion de este).
  • Informacion Undo Expired (Expirada)
    Esta información ya no es requerida por una transacción y puede ser sobreescrita por la siguiente transacción activa.
Como mencionaba arriba, los registros de undo, tambien nos sirven para mantener la consistencia de lectura de datos,que pasa cuando un query quiere obtener información del registro tipo undo, y esta información ya ha sido sobrescrita, si eso te llega a suceder, vas a ver el siguiente error ORA-01555 Snapshot Too Old . Este error lo que  te esta diciendo es que el query necesita una "fotografia" de los datos a como estaba en un punto pasado y reconstruir esta "fotografia" de datos requiere información del registro tipo undo que ya no se encuentra en él.

Oracle usa una retencion de undo (Undo Retention) manejada en segundos, cuando el tablespace de tipo undo se maneja con la opcion AUTOEXTEND, Oracle retiene la informacion de tipo undo por el tiempo minimo que el parametro UNDO_RETENTION tiene, nada mas que hay un detalle a saber, que si el tablespace ya no tiene suficiente espacio para crecer, va a empezar a utilizar espacio que ocupa la información sin expirar (UNEXPIRED), que esto puede causar un error de tipo ORA-01555.

Ahora que ya sabemos que son, que puedo hacer con esta información?
Vamos a ver un pequeño ejemplo con el usuario hr y vas a poder ver una transacción y el espacio que esta consumiendo de undo.

Primera que nada vamos a verificar el SID tenemos asignado y crear una tabla llamada prueba

TESTDB >select sys_context('USERENV','SID') from dual;
SYS_CONTEXT('USERENV','SID')
----------------------------------------------------------------
69

TESTDB >create table prueba (idprueba number);
Table created.


Con el siguiente query,verificamos que ninguna transacción esta activa en nuestra sesion, el resultado debe de ser un valor nulo.


TESTDB >select dbms_transaction.local_transaction_id from dual;
LOCAL_TRANSACTION_ID
--------------------------------------

Luego creamos un pequeño bloque de pl/sql que inserte datos en la tabla que creamos, y es muy importante que no le des commit


TESTDB >begin
  2  for i in 1..10000 loop
  3  insert into prueba values (i);
  4  end loop;
  5  end;
  6  /
PL/SQL procedure successfully completed.


Volvemos a verificar la transacción, y te vas a dar cuenta que como hicimos un insert y no hemos hecho commit, nos regresa un resultado, significando que a nuestra transacion se le asigno un identificador o XID

TESTDB >select dbms_transaction.local_transaction_id from dual;
LOCAL_TRANSACTION_ID
--------------------------------------
47.29.15324


Estos tres numeros son en el orden en que aparecen:
  • El identificador del segmento undo donde la transaccion registra su informacion undo.
  • El numero de Slot undo en el segmento undo
  • El numero secuencial en el Slot de undo

Pero esta información que te muestro arriba, dado que es util saber, normalmente tenemos que ver transacciones que no nos pertenecen, por eso existe una vista llamada v$transaction, en donde podemos verificar transacciones que esta sucediendo en otra parte. Y aqui vas a encontrar tres campos que se te van a hacer muy familiares

  • XIDUSN.-El identificador del segmento undo donde la transaccion registra su informacion undo.
  • XIDSLOT.-El numero de Slot undo en el segmento undo
  • XIDSQN.-El numero secuencial en el Slot de undo

Con el query que se encuentra abajo, puedes ver la relacion con la sesion y la cantidad de undo en megas que esta utilizando la sesion:


select r.name,s.sid,s.serial#,s.module,
    to_char(s.logon_time, 'mm/dd/yy hh24:mi:ss') as login_time,
    xidusn, xidslot, xidsqn,
    t.used_ublk * to_number(x.value)/(1024*1024) as undo_mb
from v$session s,v$transaction t,v$rollname r,v$parameter x
where s.saddr = t.ses_addr and r.usn = t.xidusn
    and x.name = 'db_block_size';


Rollback Segment      SID,Serial   Module               Login Time            XIDUSN    XIDSLOT     XIDSQN      Undo MB
--------------------- ------------ -------------------- ----------------- ---------- ---------- ---------- ------------
_SYSSMU47_1546937756$ 69,1043      SQL*Plus             01/18/11 18:35:40         47         29      15324        .9141

Conclusion
Conocimos lo que era una transacción, asi como lo que es la definición de undo, de la misma manera que una vez que una transacción inicia, se guarda en un registro tipo undo, la informacion antes de ser cometida (UNCOMMITED) para poder hacer un rollback y tambien para tener consistencia en la lectura de datos una vez que esta fue cometida (COMMITED).