Oracle
 sql >> Database >  >> RDS >> Oracle

Dumping dei blocchi di dati

Recentemente stavo lavorando su alcune corruzioni di blocchi di dati e avevo bisogno di scaricare alcuni blocchi di dati per verificarne il contenuto. Ho dovuto cancellare un foglio che ho scritto molto tempo fa che mostrava come farlo. Quella che segue è una parte di quel documento:

Per eseguire il dump di un blocco appartenente a una tabella, devi conoscere il numero di file e il numero di blocco di quel blocco. Se conosci già il numero del file e il blocco, allora sei pronto. Se non si conosce il numero di file e il blocco, è possibile interrogare DBA_EXTENTS per tali informazioni. Ora che sappiamo quali file e blocchi contengono la nostra tabella, eseguiamo il dump di un blocco di esempio della tabella. Questo viene fatto come segue:

ORA9I SQL> alter system dump datafile 3 block 10;

System altered.

Puoi scaricare un intervallo di blocchi con il seguente comando:

ORA9I SQL> alter system dump datafile 3 block min 10 block max 12;

System altered.

Diamo ora un'occhiata al contenuto del dumping di un blocco.

Start dump data blocks tsn: 3 file#: 3 minblk 10 maxblk 10
buffer tsn: 3 rdba: 0x00c0000a (3/10)
scn: 0x0000.00046911 seq: 0x02 flg: 0x04 tail: 0x69110602
frmt: 0x02 chkval: 0x579d type: 0x06=trans data
Block header dump: 0x00c0000a
Object id on Block? Y
seg/obj: 0x6d9c csc: 0x00.46911 itc: 2 flg: O typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01

Itl Xid Uba Flag Lck Scn/Fsc
0x01 xid: 0x0005.02f.0000010c uba: 0x00806f10.00ca.28 C--- 0 scn 0x0000.00046900
0x02 xid: 0x0003.01c.00000101 uba: 0x00800033.0099.04 C--- 0 scn 0x0000.00046906

Questo è l'inizio del dump del blocco dati. La prima riga ci dice che stiamo scaricando il file#3, iniziando dal blocco#10 (minblk) e finendo con il blocco#10 (maxblk). Se avessimo scaricato più di un blocco di dati, questi valori rappresenterebbero un intervallo. L'indirizzo del blocco dati relativo (rdba) è 0x00c0000a. Per ulteriori informazioni su rdba, fare riferimento a una sezione successiva in questo documento. Alla fine di questa riga, possiamo vedere tra parentesi che rdba corrisponde al file# 3, block# 10 (3/10).

La terza riga descrive l'SCN del blocco dati. Nel nostro caso, l'SCN è 0x0000.00046911. La coda del blocco dati è composta dagli ultimi due byte dell'SCN (6911) a cui sono aggiunti il ​​tipo (06) e la sequenza (02). Se la decomposizione della coda non corrisponde a questi tre valori, il sistema sa che il blocco è incoerente e deve essere recuperato. Sebbene questo valore di coda venga visualizzato all'inizio del dump del blocco, viene archiviato fisicamente alla fine del blocco di dati.

Il tipo di blocco viene visualizzato nella quarta riga. Alcuni dei tipi validi corrispondono alla seguente tabella:

Type Meaning
0x02 undo block
0x06 table or index data block
0x0e undo segment header
0x10 data segment header block
0x17 bitmapped data segment header

L'"ID oggetto sul blocco?" la riga ci dice se questo oggetto è o meno in SYS.OBJ$. Da Oracle 6, questo dovrebbe essere sempre "Y". Se guardi la riga successiva, il valore seg/obj ci dice l'id dell'oggetto del segmento (in esadecimale). Nel nostro esempio, questo è 0x6d9c. Hex '6D9C' è '28060' in decimale. Possiamo verificare che questa sia la nostra tabella con la seguente query:

ORA9I SQL> select owner,object_name from dba_objects
2 where object_id=28060;

OWNER OBJECT_NAME
---------- ------------------------------
PEASLAND EMP

Come speravamo, questo è il nostro tavolo.

Il valore csc è il numero di Cleanout System Change. Questo valore indica quando è stata eseguita la pulizia del blocco su questo blocco. Si spera che corrisponda all'SCN del blocco dati. Il valore itc è il conteggio dell'elenco delle transazioni interessate. Nel nostro caso, ci sono due transazioni interessate a questo blocco. Le transazioni interessate appaiono alla fine del nostro esempio. Possiamo vedere l'ID transazione (Xid) di queste due transazioni. Tali ID transazione corrispondono ai segmenti di rollback utilizzati per elaborare le nostre transazioni.

Il flag (flg) è “-” o “O”, usato per indicare se questo blocco è in una freelist. Se il blocco è in una freelist, il flag sarà “0”. Se non è in una freelist, la bandiera sarà "-". Il nostro blocco in questione è nella freelist.

Bene, c'erano molte informazioni e non abbiamo davvero guardato troppo alla discarica. Diamo un'occhiata alla prossima sezione del dump del blocco dati.

data_block_dump
===============
tsiz: 0x1fa0
hsiz: 0x2e
pbl: 0x024d015c
bdba: 0x00c0000a
flag=-------------
ntab=1
nrow=14
frre=9
fsbo=0x2e
fseo=0x1b18
avsp=0x1d8a
tosp=0x1d8a
0xe:pti[0] nrow=14 offs=0
0x12:pri[0] offs=0x1c30
0x14:pri[1] offs=0x1f4f
0x16:pri[2] offs=0x1f24
0x18:pri[3] offs=0x1efb
0x1a:pri[4] offs=0x1ece
0x1c:pri[5] offs=0x1ea5
0x1e:pri[6] offs=0x1e7c
0x20:pri[7] offs=0x1e54
0x22:pri[8] offs=0x1e2e
0x24:pri[9] sfll=13
0x26:pri[10] offs=0x1ca4
0x28:pri[11] offs=0x1cf1
0x2a:pri[12] offs=0x1b18
0x2c:pri[13] sfll=-1

Il valore tsiz ci mostra la quantità di spazio disponibile nel blocco per i dati. Qui, otteniamo "1fa0" che si traduce in 8.096 byte di spazio utilizzabile. Il resto del nostro blocco da 8.192 byte viene utilizzato per l'overhead come l'intestazione del blocco.

Il valore ntab ci mostra quante tabelle sono memorizzate in questo blocco. A meno che questo blocco non appartenga a un cluster, questo valore sarà "1". Il valore nrow indica quante righe di dati sono archiviate in questo blocco. Il nostro blocco dati ha 14 righe di dati.

A partire dall'indirizzo '0xe', otteniamo una directory per ogni riga. Possiamo vedere che la prima riga (voce di indice zero) inizia all'indirizzo di offset per il blocco '0x1c30'. Ciascuna delle righe dei blocchi segue da qui. In questo modo, una riga può essere trovata molto rapidamente. Ricorda che un ROWID è fondamentalmente un puntatore a una riga univoca. In Oracle 8+, il ROWID è nella forma O.F.B.R (o objectno,relativefno,blockno,rowno). Quindi, quando il sistema punta rapidamente a un blocco particolare in un file particolare, il numero di riga punta a uno slot in questa directory. La directory punta quindi a una posizione specifica nel blocco. Questo è l'inizio di quella riga.

Ora che abbiamo una roadmap per il nostro blocco di dati, esaminiamo il resto del file di traccia per vedere le effettive righe di dati nel blocco.

block_row_dump:
tab 0, row 0, @0x1c30
tl: 39 fb: --H-FL-- lb: 0x0 cc: 8
col 0: [ 3] c2 4a 46
col 1: [ 5] 53 4d 49 54 48
col 2: [ 5] 43 4c 45 52 4b
col 3: [ 3] c2 50 03
col 4: [ 7] 77 b4 0c 11 01 01 01
col 5: [ 3] c2 09 19
col 6: *NULL*
col 7: [ 2] c1 15

I dati di riga effettivi iniziano con la frase "block_row_dump:". Quindi viene fornita una riga di dati. Ho mostrato solo una riga di dati qui, poiché il resto è simile. Possiamo vedere che questa riga appartiene alla tabella '0' (tab) del nostro cluster. Poiché nel nostro esempio non è presente alcun cluster, non abbiamo più di una tabella, quindi questo valore sarà zero. Possiamo anche vedere che questa è la riga "0" e viene fornito l'indirizzo di quella riga. Questo indirizzo dovrebbe corrispondere alla nostra tabella di marcia sopra indicata.

Il valore 'tl' ci fornisce il numero totale di byte per questa riga, incluso l'eventuale sovraccarico. Possiamo vedere che questa riga occupa 39 byte. Il valore "cc" ci fornisce un conteggio delle colonne. Abbiamo otto colonne in questa riga. Questo può essere facilmente verificato eseguendo un DESCRIBE sulla tabella e contando le colonne, oppure interrogando USER_TAB_COLUMNS.

Il valore "fb" ci fornisce i flag sulla riga. 'H' significa che abbiamo la testa della fila. 'F' significa che abbiamo il primo pezzo della riga. 'L' significa che abbiamo anche l'ultimo pezzo della riga. Poiché questo è il primo e l'ultimo pezzo della riga, la riga non è concatenata. Poiché questa è anche l'intestazione della riga, la riga non è stata migrata.

Il resto delle informazioni per la riga sono i dati per ciascuna colonna. Ad esempio, nella colonna 1, abbiamo i seguenti codici di caratteri ASCII, "53 4d 49 54 48". Una rapida occhiata a un grafico di conversione ASCII ci dirà che questi caratteri sono "SMITH". Se hai familiarità con la tabella EMP di esempio, saprai che SMITH è uno dei nostri dipendenti. Si noti che la colonna 6 è NULL. La colonna 4 è la colonna HIREDATE. Questo è un tipo di dati DATE. Da questo blocco, puoi facilmente verificare che il tipo di dati DATE richieda sette byte di archiviazione. La colonna 0 contiene un numero. I tre byte qui sono la rappresentazione di quel numero.