मैं हाल ही में कुछ डेटा ब्लॉक भ्रष्टाचारों पर काम कर रहा था और मुझे इसकी सामग्री को सत्यापित करने के लिए कुछ डेटा ब्लॉक को डंप करने की आवश्यकता थी। मुझे एक पेपर को ब्रश करना पड़ा जो मैंने बहुत समय पहले लिखा था जिसमें दिखाया गया था कि यह कैसे करना है। उस पेपर का एक अंश इस प्रकार है:
किसी तालिका से संबंधित ब्लॉक को डंप करने के लिए, आपको उस ब्लॉक की फ़ाइल संख्या और ब्लॉक संख्या जानने की आवश्यकता होगी। यदि आप पहले से ही फाइल नंबर और ब्लॉक जानते हैं, तो आप पूरी तरह तैयार हैं। यदि आप फ़ाइल नंबर और ब्लॉक नहीं जानते हैं, तो आप उस जानकारी के लिए DBA_EXTENTS को क्वेरी कर सकते हैं। अब जब हम जानते हैं कि कौन सी फाइल और ब्लॉक हमारी टेबल रखते हैं, तो टेबल के सैंपल ब्लॉक को डंप करें। यह इस प्रकार किया जाता है:
ORA9I SQL> alter system dump datafile 3 block 10;
System altered.
आप निम्न आदेश के साथ कई ब्लॉकों को डंप कर सकते हैं:
ORA9I SQL> alter system dump datafile 3 block min 10 block max 12;
System altered.
आइए अब एक ब्लॉक को डंप करने की सामग्री को देखें।
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
यह डेटा ब्लॉक डंप की शुरुआत है। पहली पंक्ति हमें बताती है कि हम फ़ाइल # 3 को डंप कर रहे हैं, ब्लॉक # 10 (मिनब्ल्क) से शुरू कर रहे हैं, और ब्लॉक # 10 (मैक्सब्लैक) के साथ खत्म कर रहे हैं। यदि हम एक से अधिक डेटा ब्लॉक को डंप करते हैं, तो ये मान एक श्रेणी का प्रतिनिधित्व करेंगे। सापेक्ष डेटा ब्लॉक पता (rdba) 0x00c0000a है। rdba के बारे में अधिक जानकारी के लिए, इस पेपर के बाद के अनुभाग को देखें। इस पंक्ति के अंत में, हम कोष्ठकों में देख सकते हैं कि rdba फ़ाइल # 3, ब्लॉक # 10 (3/10) से मेल खाती है।
तीसरी पंक्ति डेटा ब्लॉक के SCN का वर्णन करती है। हमारे मामले में, एससीएन 0x0000.00046911 है। डेटा ब्लॉक की पूंछ SCN (6911) के अंतिम दो बाइट्स (06) और अनुक्रम (02) के साथ संलग्न है। यदि पूंछ का अपघटन इन तीन मूल्यों से मेल नहीं खाता है, तो सिस्टम जानता है कि ब्लॉक असंगत है और इसे पुनर्प्राप्त करने की आवश्यकता है। जबकि यह टेल वैल्यू ब्लॉक डंप की शुरुआत में दिखाई देता है, यह डेटा ब्लॉक के अंत में भौतिक रूप से संग्रहीत होता है।
ब्लॉक प्रकार चौथी पंक्ति पर दिखाई देता है। कुछ मान्य प्रकार निम्न तालिका के अनुरूप हैं:
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
"ब्लॉक पर ऑब्जेक्ट आईडी?" लाइन हमें बताती है कि यह ऑब्जेक्ट SYS.OBJ$ में है या नहीं। Oracle 6 के बाद से, यह हमेशा "Y" होना चाहिए। यदि आप अगली पंक्ति को देखते हैं, तो seg/obj मान हमें खंड की ऑब्जेक्ट आईडी (हेक्स में) बताता है। हमारे उदाहरण में, यह 0x6d9c है। हेक्स '6D9C' दशमलव में '28060' है। हम निम्न क्वेरी के साथ सत्यापित कर सकते हैं कि यह हमारी तालिका है:
ORA9I SQL> select owner,object_name from dba_objects
2 where object_id=28060;
OWNER OBJECT_NAME
---------- ------------------------------
PEASLAND EMP
जैसा कि हमने आशा की थी, यह हमारी तालिका है।
csc वैल्यू क्लीनआउट सिस्टम चेंज नंबर है। यह मान हमें बताता है कि इस ब्लॉक पर ब्लॉक क्लीनआउट कब किया गया था। उम्मीद है, यह डेटा ब्लॉक के SCN से मेल खाता है। आईटीसी मूल्य इच्छुक लेनदेन सूची गणना है। हमारे मामले में, इस ब्लॉक में रुचि रखने वाले दो लेनदेन हैं। वे इच्छुक लेन-देन हमारे उदाहरण के अंत में दिखाई देते हैं। हम उन दो लेनदेन की लेनदेन आईडी (Xid) देख सकते हैं। वे लेन-देन आईडी रोलबैक सेगमेंट से संबंधित हैं जिनका उपयोग हमारे लेनदेन को संसाधित करने के लिए किया जाता है।
ध्वज (flg) या तो "-" या "O" है, जिसका उपयोग यह इंगित करने के लिए किया जाता है कि यह ब्लॉक एक फ्रीलिस्ट पर है या नहीं। यदि ब्लॉक एक फ्रीलिस्ट पर है, तो ध्वज "0" होगा। यदि यह एक स्वतंत्र सूची में नहीं है, तो ध्वज "-" होगा। हमारा विचाराधीन ब्लॉक फ्रीलिस्ट पर है।
खैर, यह काफी जानकारी थी और हमने वास्तव में बहुत अधिक डंप नहीं देखा है। आइए डेटा ब्लॉक डंप के अगले भाग को देखें।
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
tsiz मान हमें डेटा के लिए ब्लॉक में उपलब्ध कमरे की मात्रा दिखाता है। यहां, हमें '1fa0' मिलता है जो प्रयोग करने योग्य कमरे के 8,096 बाइट्स का अनुवाद करता है। हमारे शेष 8,192 बाइट ब्लॉक का उपयोग ओवरहेड के लिए किया जाता है जैसे कि ब्लॉक हेडर।
Ntab मान हमें दिखाता है कि इस ब्लॉक में कितनी तालिकाएँ संग्रहीत हैं। जब तक यह ब्लॉक किसी क्लस्टर से संबंधित न हो, यह मान '1' होगा। Nrow मान हमें बताता है कि इस ब्लॉक में डेटा की कितनी पंक्तियाँ संग्रहीत हैं। हमारे डेटा ब्लॉक में डेटा की 14 पंक्तियाँ हैं।
पते '0xe' से शुरू होकर, हमें प्रत्येक पंक्ति के लिए एक निर्देशिका मिलती है। हम देख सकते हैं कि पहली पंक्ति (सूचकांक प्रविष्टि शून्य) ब्लॉक '0x1c30' के ऑफसेट पते पर शुरू होती है। प्रत्येक ब्लॉक पंक्तियाँ यहाँ से चलती हैं। इस तरह, एक पंक्ति वास्तव में जल्दी से मिल सकती है। याद रखें कि ROWID मूल रूप से एक अद्वितीय पंक्ति का सूचक है। Oracle 8+ में, ROWID O.F.B.R (या ऑब्जेक्टनो, रिलेटिवेफ़नो, ब्लॉकनो, रोनो) के रूप में है। इसलिए जब सिस्टम किसी विशेष फ़ाइल में किसी विशेष ब्लॉक को तुरंत इंगित करता है, तो पंक्ति संख्या इस निर्देशिका में एक स्लॉट को इंगित करती है। निर्देशिका तब ब्लॉक में एक विशिष्ट स्थान की ओर इशारा करती है। यह उस पंक्ति की शुरुआत है।
अब जबकि हमारे पास अपने डेटा ब्लॉक का रोडमैप है, आइए ब्लॉक में डेटा की वास्तविक पंक्तियों को देखने के लिए शेष ट्रेस फ़ाइल को देखें।
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
वास्तविक पंक्ति डेटा "block_row_dump:" वाक्यांश से शुरू होता है। फिर डेटा की एक पंक्ति दी जाती है। मैंने यहां डेटा की केवल एक पंक्ति दिखाई है, क्योंकि बाकी समान है। हम देख सकते हैं कि यह पंक्ति हमारे क्लस्टर की तालिका '0' (टैब) से संबंधित है। चूंकि हमारे उदाहरण में कोई क्लस्टर नहीं है, हमारे पास एक से अधिक टेबल नहीं हैं, इसलिए यह मान शून्य होगा। हम यह भी देख सकते हैं कि यह पंक्ति '0' है और उस पंक्ति का पता दिया गया है। यह पता ऊपर उल्लिखित हमारे रोडमैप के अनुरूप होना चाहिए।
'टीएल' मान हमें इस पंक्ति के लिए बाइट्स की कुल संख्या देता है, जिसमें कोई ओवरहेड भी शामिल है। हम देख सकते हैं कि यह पंक्ति 39 बाइट्स रखती है। 'सीसी' मान हमें एक कॉलम काउंट देता है। इस पंक्ति में हमारे पास आठ कॉलम हैं। इसे टेबल पर DESCRIBE करके और कॉलम गिनकर या USER_TAB_COLUMNS को क्वेरी करके आसानी से सत्यापित किया जा सकता है।
'fb' मान हमें पंक्ति के बारे में संकेत देता है। 'H' का अर्थ है कि हमारे पास पंक्ति का शीर्ष है। 'F' का अर्थ है कि हमारे पास पंक्ति का पहला भाग है। 'L' का अर्थ है कि हमारे पास पंक्ति का अंतिम भाग भी है। चूंकि यह पंक्ति का पहला और आखिरी टुकड़ा है, इसलिए पंक्ति जंजीर नहीं है। चूंकि यह पंक्ति का प्रमुख भी है, इसलिए पंक्ति को माइग्रेट नहीं किया गया है।
पंक्ति के लिए शेष जानकारी प्रत्येक कॉलम का डेटा है। उदाहरण के लिए, कॉलम 1 में, हमारे पास निम्नलिखित ASCII वर्ण कोड हैं, "53 4d 49 54 48"। एएससीआईआई रूपांतरण चार्ट पर एक त्वरित नज़र हमें बताएगी कि ये वर्ण "स्मिथ" हैं। यदि आप नमूना ईएमपी तालिका से परिचित हैं, तो आप जानेंगे कि स्मिथ हमारे कर्मचारियों में से एक है। ध्यान दें कि कॉलम 6 NULL है। कॉलम 4 हायरडेट कॉलम है। यह एक DATE डेटाटाइप है। इस ब्लॉक से, आप आसानी से सत्यापित कर सकते हैं कि DATE डेटाटाइप को सात बाइट संग्रहण की आवश्यकता है। कॉलम 0 में एक संख्या है। यहाँ तीन बाइट उस संख्या का प्रतिनिधित्व करते हैं।