Ik werkte onlangs aan een aantal corrupties van gegevensblokken en ik moest enkele gegevensblokken dumpen om de inhoud ervan te verifiëren. Ik moest een papier wegpoetsen dat ik lang geleden had geschreven en waarin stond hoe je dit moest doen. Wat volgt is een deel van dat document:
Om een blok dat bij een tabel hoort te dumpen, moet je het bestandsnummer en bloknummer van dat blok weten. Als u het bestandsnummer en blok al kent, bent u helemaal klaar. Als u het bestandsnummer en de blokkering niet weet, kunt u die informatie opvragen bij DBA_EXTENTS. Nu we weten welk bestand en welke blokken onze tabel bevatten, laten we een voorbeeldblok van de tabel dumpen. Dit gaat als volgt:
ORA9I SQL> alter system dump datafile 3 block 10;
System altered.
Je kunt een reeks blokken dumpen met het volgende commando:
ORA9I SQL> alter system dump datafile 3 block min 10 block max 12;
System altered.
Laten we nu eens kijken naar de inhoud van het dumpen van één blok.
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
Dit is het begin van de datablokdump. De eerste regel vertelt ons dat we bestand #3 dumpen, beginnend bij blok# 10 (minblk) en eindigend met blok# 10 (maxblk). Als we meer dan één gegevensblok hadden gedumpt, zouden deze waarden een bereik vertegenwoordigen. Het relatieve datablokadres (rdba) is 0x00c0000a. Raadpleeg een later gedeelte in dit document voor meer informatie over de rdba. Aan het einde van deze regel kunnen we tussen haakjes zien dat de rdba overeenkomt met bestand # 3, blok # 10 (3/10).
De derde regel beschrijft de SCN van het datablok. In ons geval is de SCN 0x0000.00046911. De staart van het datablok bestaat uit de laatste twee bytes van de SCN (6911) met daaraan toegevoegd het type (06) en de reeks (02). Als de ontbinding van de staart niet overeenkomt met deze drie waarden, weet het systeem dat het blok inconsistent is en moet worden hersteld. Hoewel deze staartwaarde aan het begin van de blokdump verschijnt, wordt deze fysiek opgeslagen aan het einde van het gegevensblok.
Het bloktype verschijnt op de vierde regel. Enkele van de geldige typen komen overeen met de volgende tabel:
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
De "Object-ID op blok?" regel vertelt ons of dit object al dan niet in SYS.OBJ$ staat. Sinds Oracle 6 moet dit altijd "Y" zijn. Als je naar de volgende regel kijkt, vertelt de seg/obj-waarde ons de object-id van het segment (in hex). In ons voorbeeld is dit 0x6d9c. Hex '6D9C' is '28060' in decimaal. We kunnen verifiëren dat dit onze tabel is met de volgende vraag:
ORA9I SQL> select owner,object_name from dba_objects
2 where object_id=28060;
OWNER OBJECT_NAME
---------- ------------------------------
PEASLAND EMP
Zoals we hadden gehoopt, is dit onze tafel.
De csc-waarde is het Cleanout System Change-nummer. Deze waarde vertelt ons wanneer blokopruiming op dit blok is uitgevoerd. Hopelijk komt het overeen met de SCN van het datablok. De itc-waarde is het aantal geïnteresseerde transacties. In ons geval zijn er twee transacties geïnteresseerd in dit blok. Die geïnteresseerde transacties verschijnen aan het einde van ons voorbeeld. We kunnen de transactie-ID (Xid) van die twee transacties zien. Die transactie-ID's komen overeen met terugdraaisegmenten die worden gebruikt om onze transacties te verwerken.
De vlag (flg) is ofwel "-" of "O", gebruikt om aan te geven of dit blok op een vrije lijst staat. Als het blok op een vrije lijst staat, is de vlag "0". Als het niet op een vrije lijst staat, is de vlag "-". Ons blok in kwestie staat op de vrije lijst.
Nou, dat was best veel informatie en we hebben niet echt naar te veel van de stortplaats gekeken. Laten we eens kijken naar het volgende gedeelte van de datablokdump.
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
De tsiz-waarde toont ons de hoeveelheid beschikbare ruimte in het blok voor gegevens. Hier krijgen we '1fa0' wat zich vertaalt naar 8.096 bytes bruikbare ruimte. De rest van ons 8192-byte-blok wordt gebruikt voor overhead, zoals de blokheader.
De ntab-waarde laat ons zien hoeveel tabellen er in dit blok zijn opgeslagen. Tenzij dit blok tot een cluster behoort, is deze waarde '1'. De waarde nrow vertelt ons hoeveel rijen gegevens in dit blok zijn opgeslagen. Ons datablok heeft 14 rijen met data.
Vanaf adres '0xe' krijgen we een map naar elke rij. We kunnen zien dat de eerste rij (indexinvoer nul) begint bij het offsetadres naar het blok '0x1c30'. Elk van de blokkenrijen volgt vanaf hier. Zo is een rij heel snel terug te vinden. Onthoud dat een ROWID in feite een verwijzing naar een unieke rij is. In Oracle 8+ heeft de ROWID de vorm O.F.B.R (of objectno,relativefno,blockno,rowno). Dus als het systeem snel naar een bepaald blok in een bepaald bestand wijst, wijst het rijnummer naar een slot in deze map. De directory wijst dan naar een specifieke locatie in het blok. Dit is het begin van die rij.
Nu we een routekaart naar ons gegevensblok hebben, gaan we naar de rest van het traceerbestand kijken om de daadwerkelijke gegevensrijen in het blok te zien.
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
De daadwerkelijke rijgegevens beginnen met de zin "block_row_dump:". Vervolgens wordt een rij gegevens gegeven. Ik heb hier slechts één rij gegevens weergegeven, omdat de rest vergelijkbaar is. We kunnen zien dat deze rij hoort bij tabel '0' (tabblad) van ons cluster. Omdat er in ons voorbeeld geen cluster is, hebben we niet meer dan één tabel, dus deze waarde is nul. We kunnen ook zien dat dit rij '0' is en het adres van die rij wordt gegeven. Dit adres moet overeenkomen met onze hierboven vermelde routekaart.
De 'tl'-waarde geeft ons het totale aantal bytes voor deze rij, inclusief eventuele overhead. We kunnen zien dat deze rij 39 bytes in beslag neemt. De 'cc'-waarde geeft ons een kolomtelling. We hebben acht kolommen in deze rij. Dit kan eenvoudig worden geverifieerd door een DESCRIBE op de tabel te doen en de kolommen te tellen, of door USER_TAB_COLUMNS op te vragen.
De 'fb'-waarde geeft ons vlaggen over de rij. 'H' betekent dat we de kop van de rij hebben. 'F' betekent dat we het eerste stuk van de rij hebben. 'L' betekent dat we ook het laatste stuk van de rij hebben. Aangezien dit het eerste en laatste stuk van de rij is, is de rij niet geketend. Aangezien dit ook de kop van de rij is, is de rij niet gemigreerd.
De rest van de informatie voor de rij zijn de gegevens voor elke kolom. In kolom 1 hebben we bijvoorbeeld de volgende ASCII-tekencodes, "53 4d 49 54 48". Een snelle blik op een ASCII-conversietabel zal ons vertellen dat deze tekens "SMITH" zijn. Als u bekend bent met de voorbeeld EMP-tabel, dan weet u dat SMITH een van onze medewerkers is. Merk op dat kolom 6 NULL is. Kolom 4 is de HIREDATE-kolom. Dit is een DATE-gegevenstype. Vanuit dit blok kunt u eenvoudig controleren of het datatype DATE zeven bytes aan opslagruimte vereist. Kolom 0 bevat een getal. De drie bytes hier zijn de representatie van dat nummer.