UNDO Data

-- Versione Oracle 11g

Nelle operazioni di flashback query, flashback transaction e table o Recovery from failed transaction sono fondamentali gli Undo data.
Gli Undo Data sono copie di dati sottoposti ad una transazione e sono mantenuti finché la transazione non termina con una commit, rollback, ddl o una sessione terminata "abnormally" o con il comando shutdown abort.  Quindi il tablespace Undo è come un tablespace temporaneo.
I dati di undo sopravvivono alla chiusura del database.
Ogni transazione è assegnata ad un solo Undo Segment ma un Undo Segment può service più transazioni contemporaneamente.
Ogni volta che c'è una richiesta di update, il server process (vedi post Listener: connessione - sessione) copia alcuni blocchi di undo datafile nel Database Buffer Cache, e salva qui il valore dei dati prima della modifica.
Finché non viene eseguita la commit i vecchi dati sono sempre visibili da una secondo utente che esegue la stessa query: è in questo che consiste la READ CONSISTENCY.
Inoltre è possibile effettuare il rollback dei dati. 
E' possibile vedere a quale undo segment è associata una transazione interrogando la vista dinamica  V$TRANSACTION.

N.B. Undo segment sono classici segment quindi composti da extent e blocchi.


Esempio di READ CONSISTENCY


Ad esempio il primo utente che esegue la update sulla tabella T legge il valore "Jacob". Se non ha ancora eseguito il comando commit, il secondo utente che effettua una select sulla stessa tabella T  legge ancora il valore "Frank". 
Questo avviene perché il Server Process#1 aggiorna un campo dell'header del blocco (presente nel database buffer cache), chiamato Transaction Slot, che contiene i dettagli della transazione in corso con gli estremi di chi ha fatto la modifica e le informazioni relative al blocco undo contenente il vecchio valore. Quindi il Server Process#2 con la select, legge il TS  e viene indirizzato sul blocco undo che contiene il vecchio valore "Frank".




Di default i parametri di inizializzazione del database sono impostati come segue:

SQL> show parameter undo;
UNDO_MANAGEMENT='AUTO'
UNDO_TABLESPACE='UNDOTBS1'
UNDO_RETENTION=900 (tempo in secondi)


oppure

SQL> select * from v$parameter where name like '%undo%';

SQL> show parameter undo_tablespace
NAME              TYPE          VALUE
----------------------------------------- 
undo_tablespace  string         UNDOTBS1



UNDO_MANGEMENT= 'AUTO' 
noto come AUM  è abilitato di default nella versione oralce 11g mentre in quelle precedenti è null. Quindi in fase di migrazione del db da un versione precedente fare attenzione a questo parametro. L'impostazione AUTO significa che in automatico viene gestito la dimensione del tablespace UNDOTBS1 e quindi è di tipo autoextend con maxsize unlimited (in realtà si estende fino a 32GB).
Questa impostanzione implica che il db da solo aggiusta il parametro di undo_retention in base al più lungo tempo di esecuzione di una Flashback Operation o delle query o dml attive  perchè deve garantire la read consistency

UNDO RETENTION= 900
esprime per quanto tempo in secondi sono conservate i vecchi valori al termine di una transazione e può essere cambiata con il comando seguente:
SQL> ALTER SYSTEM SET undo_retention=1440 scope=both;
In generale il valore di Undo Retention è impostato ugale al più lungo tempo di esecuzione di una Flashback Operation o delle query o dml attive.


I dati di undo hanno tre stati o categorie:
uncommitted --> active undo e serve per il rollback di una transazione. Per questo non possono mai essere sovrascritti perchè contiene dati non commitati che potrebbero essere rollbackati.
unexpired --> sono gli undo data committati. Quando si effettua la commit gli undo data passano allo stato unexpired e quindi non possono essere utilizzati per il tempo di retention perchè servono per "read consistency" e Oracle Flashback operations.
expired --> Trascorso il tempo di retention, gli undo data passano allo stato expired e quindi possono nuovamente essere utilizzati o sovrascritti. Per questo motivo si dice che gli undo segment sono circolari.

Se arriva una nuova transazione e lo spazio del tablespace undo è pieno e non ci sono undo data in stato expired, AUM cerca di estendere il tablespace Undo ma se questo non è autoextend  o non si è impostato maxsize unlimited allora sovrascrive gli undo unexpired piuttosto che bloccare la transazione.
Se si vuole invece conservare gli undo data expired (e quindi appartenenti a transazioni committate e quindi vecchi valori)  anche a scapito del fallimento di transazioni (perché non c'è più spazio nel tablespace e i data sono in stato unexiperd, come detto prima), occorre abilitare l'attributo RETENTION GUARANTEE del tablespace Undo.

SQL> ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;

Questa opzione mi garantisce di conservare il vecchio valore dei dati per tutto il tempo di rentention anche se si dovessero presentare nuove transazioni e non c'è spazio sul tablespace di undo e non ci sono undo data da sovrascrivere.

SQL> ALTER TABLESPACE undotbs1 RETENTION NOGUARANTEE;

Se non c'è sufficiente spazio nel tablespace undo compare il messaggio 
ORA 01555 - Snapshot too old.

La dimensione UNDO può essere controllata con il parametro undo_retention e la dimensione del tablespace UNDO e le impostazioni per questi sono determinate dal livello di attività delle DML nel database.

La colonna TUNED_UNDORETENTION della vista V$UNDOSTAT indica per quanto tempo è conservato un undo nel tablespace di riferimento. 

La vista V$transaction individua a quali undo segments è associata una transazione.

E s e m p i o
Supponiamo di avere una tabelle così fatta

SQL> select * from PDBTSADM.dept;

   DEPTNO     DEPT_NAME                                                                                           
---------- -----------------------------------
         1             IT Dept                                                                                             
         2             FINANCE  


SQL> update PDBTSADM.dept set dept_name='XXX';

Query che individua le righe presenti nel tablespace undo.

SQL> select a.sid, a.serial#, a.username, b.used_urec, b.used_ublk
from v$session a, v$transaction b 
where a.saddr=b.ses_addr; 

SID    SERIAL#  USERNAME     USED_UREC     USED_UBLK
-----------------------------------------------------
79     7253   PDBTSADM        2                1

USED_UREC = numero di undo record occupati dalla transazione
USED_BLOCK = numero di undo block occupati dalla transazione 
La sessione 79 ha creato 2 record all'interno dell'area UNDO contenuti in un solo bloco di undo.
Quindi nell'undo tablespace ho un blocco contenente due righe modificate.

A seguito del commit o del rollback la query di prima non resituisce record perchè sono liberati gli undo block all'interno del undo segment.

Post popolari in questo blog

Create e Drop Pluggable Database

ORA-12154: TNS: il listener non è attualmente a conoscenza del servizio richiesto nel descrittore di connessione